2013-06-06 21 views
26

Mục tiêu: phát hành sự kiện khi các mục trong danh sách thả xuống combobox được chọn.Trình xử lý sự kiện nào được sử dụng cho mục ComboBox được chọn (Mục đã chọn không nhất thiết phải thay đổi)

Vấn đề: Sử dụng "SelectionChanged", tuy nhiên, nếu người dùng chọn cùng một mục với mục hiện đang được chọn thì lựa chọn sẽ không thay đổi và do đó sự kiện này sẽ không được kích hoạt.

Câu hỏi: Trình xử lý sự kiện khác (hoặc những cách khác) tôi có thể sử dụng để phát hành sự kiện bất kể mục đã chọn được thay đổi hay không miễn là chuột được nhấp vào mục đó và mục đó đang được chọn.

(Làm rõ: Vấn đề là làm thế nào để kích hoạt "một cái gì đó" khi cùng một mục đang được chọn một lần nữa. Không có bản sao trong danh sách thả xuống. Kịch bản: lần đầu tiên chọn mục 1, đóng thả xuống Và sau đó một lần nữa, mở thả xuống hộp và chọn mục 1 khi một số chức năng được kích hoạt.)

Giải pháp: hiện tại có vẻ như không có giải pháp thẳng nào để thực hiện việc này. Nhưng theo từng dự án riêng lẻ, có thể có cách để làm việc xung quanh nó. (Xin vui lòng cập nhật nếu có thực sự là cách tốt để làm điều này). Cảm ơn.

+1

Không sử dụng sự kiện trong WPF. Tạo một ViewModel thích hợp và sử dụng DataBinding và các thuộc tính đơn giản để thay thế. –

+0

Có phải ** có ** là sự kiện không? WPF cung cấp ràng buộc dữ liệu, cho phép bạn liên kết 'SelectedItem' của ComboBox của bạn với thuộc tính DataContext của khung nhìn của bạn – Thelonias

+0

Xin chào, cảm ơn đề xuất của bạn. Tôi đã thử phương pháp này sau khi nhìn thấy bình luận của bạn. Những gì tôi đã làm là: Bind SelectedItem (cũng đã thử SelectedIndex) vào một thuộc tính trong ViewModel và trong setter làm một số logic mà tôi sẽ làm gì nếu có một sự kiện "SelectionChanged". Tuy nhiên, điều này vẫn không thể giải quyết được vấn đề khi mục được chọn giống như trước, setter sẽ không được kích hoạt. Tôi có thể thiếu một cái gì đó ở đây. – grc

Trả lời

1

Bạn có thể thử "SelectedIndexChanged", nó sẽ kích hoạt sự kiện ngay cả khi cùng một mục được chọn.

+0

Cảm ơn bạn đã trả lời nhanh chóng. Tôi không thấy tùy chọn này từ combobox mặc dù, là C# WPF này? – grc

+0

Tôi chỉ nhận thấy đó là WPF, trong trường hợp đó vấn đề đã được đăng ở đây http://stackoverflow.com/questions/7738899/selectionchanged-event-of-wpf-combobox-is-not-firing-if-it-has -same-items-in-it –

+0

đó là một bài đăng hữu ích. (Tôi giả định trong bài viết, "cùng một mục" được kiểm tra để được bình đẳng bằng cách sử dụng địa chỉ bộ nhớ của họ và do đó phân biệt giữa các bản sao) Tuy nhiên trong danh sách hộp combo của tôi, không có bản sao. Những gì tôi muốn là: nếu tôi chọn mục 1 lần đầu tiên. Và sau đó tôi mở trình đơn thả xuống và chọn lại mục 1, một chức năng có thể được kích hoạt. – grc

5

Bạn có thể sử dụng sự kiện "ComboBoxItem.PreviewMouseDown". Vì vậy, mỗi khi chuột rơi xuống một số mục, sự kiện này sẽ được kích hoạt.

Để thêm sự kiện này trong XAML sử dụng "ComboBox.ItemContainerStyle" như trong ví dụ tiếp theo:

<ComboBox x:Name="MyBox" 
     ItemsSource="{Binding MyList}" 
     SelectedValue="{Binding MyItem, Mode=OneWayToSource}" > 
     <ComboBox.ItemContainerStyle> 
      <Style> 
       <EventSetter Event="ComboBoxItem.PreviewMouseDown" 
        Handler="cmbItem_PreviewMouseDown"/> 
      </Style> 
     </ComboBox.ItemContainerStyle> 
    </ComboBox> 

và xử lý nó như bình thường

void cmbItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    //...do your item selection code here... 
} 

Nhờ MSDN

9

tôi đã có cùng một câu hỏi và cuối cùng tôi đã tìm thấy câu trả lời:

Bạn cần xử lý cả hai sự kiện SelectionChanged và DropDownClosed như thế này:

Trong XAML:

<ComboBox Name="cmbSelect" SelectionChanged="ComboBox_SelectionChanged" DropDownClosed="ComboBox_DropDownClosed"> 
    <ComboBoxItem>1</ComboBoxItem> 
    <ComboBoxItem>2</ComboBoxItem> 
    <ComboBoxItem>3</ComboBoxItem> 
</ComboBox> 

Trong C#:

private bool handle = true; 
private void ComboBox_DropDownClosed(object sender, EventArgs e) { 
    if(handle)Handle(); 
    handle = true; 
} 

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { 
    ComboBox cmb = sender as ComboBox; 
    handle = !cmb.IsDropDownOpen; 
    Handle(); 
} 

private void Handle() { 
    switch (cmbSelect.SelectedItem.ToString().Split(new string[] { ": " }, StringSplitOptions.None).Last()) 
    { 
     case "1": 
      //Handle for the first combobox 
      break; 
     case "2": 
      //Handle for the second combobox 
      break; 
     case "3": 
      //Handle for the third combobox 
      break; 
    } 
} 
0

Vấn đề này làm tôi phát cáu trong một thời gian dài kể từ khi không ai trong số các công việc xung quanh đã làm việc cho tôi: (

Nhưng tin vui là, phương pháp sau hoạt động tốt cho đơn đăng ký của tôi.

Ý tưởng cơ bản là để đăng ký một EventManager trong App.xmal.cs để sniff PreviewMouseLeftButtonDownEvent cho tất cả ComboBoxItem, sau đó kích hoạt các SelectionChangedEvent nếu mục chọn cũng giống như mục đã chọn, ví dụ: lựa chọn được thực hiện mà không thay đổi chỉ số.

Trong App.xmal.cs:

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     // raise selection change event even when there's no change in index 
     EventManager.RegisterClassHandler(typeof(ComboBoxItem), UIElement.PreviewMouseLeftButtonDownEvent, 
              new MouseButtonEventHandler(ComboBoxSelfSelection), true); 

     base.OnStartup(e); 
    } 

    private static void ComboBoxSelfSelection(object sender, MouseButtonEventArgs e) 
    { 
     var item = sender as ComboBoxItem; 

     if (item == null) return; 

     // find the combobox where the item resides 
     var comboBox = ItemsControl.ItemsControlFromItemContainer(item) as ComboBox; 

     if (comboBox == null) return; 

     // fire SelectionChangedEvent if two value are the same 
     if ((string)comboBox.SelectedValue == (string)item.Content) 
     { 
      comboBox.IsDropDownOpen = false; 
      comboBox.RaiseEvent(new SelectionChangedEventArgs(Selector.SelectionChangedEvent, new ListItem(), new ListItem())); 
     } 
    } 
} 

Sau đó, cho tất cả các hộp kết hợp, đăng ký SelectionChangedEvent theo một cách bình thường:

<ComboBox ItemsSource="{Binding BindList}" 
      SelectionChanged="YourSelectionChangedEventHandler"/> 

Bây giờ, nếu hai chỉ số khác nhau, không có gì đặc biệt nhưng việc xử lý sự kiện bình thường quá trình; nếu hai chỉ số giống nhau, sự kiện Chuột trên mục trước tiên sẽ được xử lý và do đó kích hoạt SelectionChangedEvent. Theo cách này, cả hai tình huống sẽ kích hoạt SelectionChangedEvent :)

0

Đây là DependencyObject để đính kèm vào ComboBox.

Nó ghi lại mục hiện được chọn khi trình đơn thả xuống được mở và sau đó kích hoạt sự kiện SelectionChanged nếu cùng một chỉ mục vẫn được chọn khi menu thả xuống được đóng lại. Nó có thể cần phải được sửa đổi để nó hoạt động với lựa chọn Bàn phím.

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 
using System.Web.UI.WebControls; 

namespace MyNamespace 
{ 
    public class ComboAlwaysFireSelection : DependencyObject 
    { 
     public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached(
      "Active", 
      typeof(bool), 
      typeof(ComboAlwaysFireSelection), 
      new PropertyMetadata(false, ActivePropertyChanged)); 

     private static void ActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var element = d as ComboBox; 
      if (element == null) 
       return; 

      if ((e.NewValue as bool?).GetValueOrDefault(false)) 
      { 
       element.DropDownClosed += ElementOnDropDownClosed; 
       element.DropDownOpened += ElementOnDropDownOpened; 
      } 
      else 
      { 
       element.DropDownClosed -= ElementOnDropDownClosed; 
       element.DropDownOpened -= ElementOnDropDownOpened; 
      } 
     } 

     private static void ElementOnDropDownOpened(object sender, EventArgs eventArgs) 
     { 
      _selectedIndex = ((ComboBox) sender).SelectedIndex; 
     } 

     private static int _selectedIndex; 

     private static void ElementOnDropDownClosed(object sender, EventArgs eventArgs) 
     { 
      var comboBox = ((ComboBox) sender); 
      if (comboBox.SelectedIndex == _selectedIndex) 
      { 
       comboBox.RaiseEvent(new SelectionChangedEventArgs(Selector.SelectionChangedEvent, new ListItemCollection(), new ListItemCollection())); 
      } 
     } 

     [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)] 
     [AttachedPropertyBrowsableForType(typeof(ComboBox))] 
     public static bool GetActive(DependencyObject @object) 
     { 
      return (bool)@object.GetValue(ActiveProperty); 
     } 

     public static void SetActive(DependencyObject @object, bool value) 
     { 
      @object.SetValue(ActiveProperty, value); 
     } 
    } 
} 

và thêm tiền tố không gian tên của bạn để có thể truy cập được.

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:ut="clr-namespace:MyNamespace" ></UserControl> 

và sau đó bạn cần phải đính kèm nó như vậy

<ComboBox ut:ComboAlwaysFireSelection.Active="True" /> 
5

Đối với tôi ComboBox.DropDownClosed tổ chức sự kiện đã làm nó.

private void cbValueType_DropDownClosed(object sender, EventArgs e) 
    { 
     if (cbValueType.SelectedIndex == someIntValue) //sel ind already updated 
     { 
      // change sel Index of other Combo for example 
      cbDataType.SelectedIndex = someotherIntValue; 
     } 
    } 
1

Sử dụng SelectionChangeCommitted(object sender, EventArgs e) kiện here

+4

đây là WPF không phải là Winforms! –

2

Đối UWP (Windows Store) ứng dụng không có ở trên sẽ làm việc (PointerPressed không lửa, không Preview, DropDownClosed hoặc các sự kiện SelectedIndexChanged tồn tại)

tôi đã phải nghỉ mát để một nút trong suốt che phủ các ComboBox (nhưng không phải của nó thả xuống mũi tên). Khi bạn nhấn vào mũi tên, danh sách sẽ giảm xuống như thường lệ và sự kiện SelectionChanged của Combo Box sẽ kích hoạt. Khi bạn nhấp vào bất kỳ nơi nào khác trên Hộp tổ hợp, sự kiện nhấp của nút trong suốt sẽ cho phép bạn chọn lại giá trị hiện tại của Hộp tổ hợp.

Một số mã XAML làm việc:

   <Grid x:Name="ComboOverlay" Margin="0,0,5,0"> <!--See comments in code behind at ClickedComboButValueHasntChanged event handler--> 
        <ComboBox x:Name="NewFunctionSelect" Width="97" ItemsSource="{x:Bind Functions}" 
          SelectedItem="{x:Bind ChosenFunction}" SelectionChanged="Function_SelectionChanged"/> 
        <Button x:Name="OldFunctionClick" Height="30" Width="73" Background="Transparent" Click="ClickedComboButValueHasntChanged"/> 
       </Grid> 

Một số mã C# làm việc:

/// <summary> 
    /// It is impossible to simply click a ComboBox to select the shown value again. It always drops down the list of options but 
    ///  doesn't raise SelectionChanged event if the value selected from the list is the same as before 
    ///  
    /// To handle this, a transparent button is overlaid over the ComboBox (but not its dropdown arrow) to allow reselecting the old value 
    /// Thus clicking over the dropdown arrow allows the user to select a new option from the list, but 
    ///  clicking anywhere else in the Combo re-selects the previous value 
    /// </summary> 
    private void ClickedComboButValueHasntChanged(object sender, RoutedEventArgs e) 
    { 
     //You could also dummy up a SelectionChangedEvent event and raise it to invoke Function_SelectionChanged handler, below 
     FunctionEntered(NewFunctionSelect.SelectedValue as string); 
    } 

    private void Function_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     FunctionEntered(e.AddedItems[0] as string); 
    } 
2

Tôi hy vọng rằng bạn sẽ tìm thấy hữu ích lừa sau.

Bạn có thể ràng buộc cả hai sự kiện

combobox.SelectionChanged += OnSelectionChanged; 
combobox.DropDownOpened += OnDropDownOpened; 

Và lực chọn mục null bên trong OnDropDownOpened

private void OnDropDownOpened(object sender, EventArgs e) 
{ 
    combobox.SelectedItem = null; 
} 

Và làm những gì bạn cần với mục bên trong OnSelectionChanged. Các OnSelectionChanged sẽ được nâng lên mỗi khi bạn sẽ mở ra combobox, nhưng bạn có thể kiểm tra xem SelectedItem là null bên trong phương pháp này và bỏ qua lệnh

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (combobox.SelectedItem != null) 
     { 
      //Do something with the selected item 
     } 
    } 
0

Mỗi ComboBoxItem dụ có sự kiện PreviewMouseDown. Nếu bạn sẽ đăng ký xử lý tùy chỉnh của bạn trên sự kiện này trên mỗi ComboBoxItem bạn sẽ có cơ hội để xử lý mỗi nhấp chuột vào danh sách thả xuống.

// Subscribe on ComboBoxItem-s events. 
comboBox.Items.Cast<ComboBoxItem>().ToList().ForEach(i => i.PreviewMouseDown += ComboBoxItem_PreviewMouseDown); 

private void ComboBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    // your handler logic...   
} 
Các vấn đề liên quan