当 ComboBox 为时如何处理 SelectionChange

问题描述

我有一个 ListBox,其中的列表元素有一个 ComboBox一个 TextBox一个滑块。根据 ComboBox 的选择,TextBox 或滑块应该可见。

    <ListBox Name="lstPWM" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDeFinitions>
                        <ColumnDeFinition Width="80"/>
                    <!-- more deFinitions -->
                    </Grid.ColumnDeFinitions>
                    <ComboBox   ItemsSource="{Binding Path=Gebertyp,Converter={local1:EnumToCollectionConverter},Mode=OneTime}"
                                SelectedValuePath="Value"
                                displayMemberPath="Description"
                                SelectionChanged="PWMTyp_SelectionChanged"
                                SelectedValue="{Binding Path=Gebertyp}" />
                    <TextBox Visibility="{Binding GeberVisible}" Text="{Binding GeberNmr,Mode=TwoWay}"/>
                   
                    <Slider   Visibility="{Binding WertVisible}" Value="{Binding Wert,Mode=TwoWay}"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

背后的代码是:

    public partial class MainWindow : Window
    {
       public ObservableCollection<PWMKanal> PWM_col { get; set; } = new();

        private void Window_Loaded(object sender,RoutedEventArgs e)
        {
            lstPWM.ItemsSource = PWM_col;
            foreach (var item in Board.PWM)  PWM_col.Add(item); //Board.PWM is the data source.
        }
       private void PWMTyp_SelectionChanged(object sender,SelectionChangedEventArgs e)
        {
            ComboBox Box = sender as ComboBox;           // Finding the line in the ListBox.
            PWMKanal PWM = Box.DataContext as PWMKanal;   
            int z = PWM_col.IndexOf(PWM);
            Board.PWM[z].Gebertyp = (QuellePWM)Box.SelectedValue;
            if (Board.PWM[z].Gebertyp == QuellePWM.Sender)
            {
                PWM_col[z].GeberVisible = Visibility.Visible; // I thought that i may change the 
                PWM_col[z].WertVisible = Visibility.Hidden;   // ObservableColelction directly
             }                                                // but the display is not updated.
                else                                          // In Debug mode i see,that PWM_coll
             {                                                // is changed as expected,but no effect 
                PWM_col[z].GeberVisible = Visibility.Hidden;  // on the GUI.
                PWM_col[z].WertVisible = Visibility.Visible;
              }
              if (PWM_col.Count != 0) // this code is intended to update the GUI,but every time
              {                       // a new item is added the Selection Change fires again
                  PWM_col.Clear();    // and i get a stack overflow in an endless loop.
                  foreach (var item in Board.PWM) PWM_col.Add(item);
              }
            
        }
    }

评论描述了我的方法和问题:

  1. 我直接更改了 ObservableCollection 的选定元素,但这对 GUI 没有影响。至少代码不会崩溃。
  2. 我清除了列表 ObservableCollection PWM_col,但随后出现了无限循环:每次将元素添加到列表中时,SelectionChange 事件都会触发,再次调用例程。结果是堆栈溢出。

现在我对我的方法的问题:

  1. 是否可以直接通过代码更改ObservableCollection的某个元素,并自动刷新显示
  2. 是否有可能在处理程序执行之前以某种方式捕获 SelectionChanged 事件?或者是否可以暂时禁用该事件?
  3. 还有其他想法吗?

感谢您的帮助!

解决方法

  1. CollectionChanged 确实通知了该集合本身,而不是 单品,变了。因此要查看更改项的 属性需要实现 INotifyPropertyChanged。同时删除 Mode=OneTime

  2. 您当然可以设置标志,即 PWMTyp_SelectionChanged 是 运行:

    private bool selChangedIsRunning = false; 私有无效PWMTyp_SelectionChanged(对象发送者,SelectionChangedEventArgs e) { 如果(selChangedIsRunning)返回; selChangedIsRunning = true; // 做东西 .... selChangedIsRunning = false; }

  3. 其他想法是 - 不要使用 SelectionChange 事件,但要绑定 Slider.VisibilityTextBox.VisibilityComboBox.SelectedValue 并使用值转换器来定义 Visibilty,您也可以使用 ConverterParameter

<ComboBox x:Name="CmbPWMTyp"  ItemsSource="{Binding Path=Gebertyp,Converter={local1:EnumToCollectionConverter},Mode=OneTime}"
                    SelectedValuePath="Value"
                    DisplayMemberPath="Description"
                    SelectionChanged="PWMTyp_SelectionChanged"
                    SelectedValue="{Binding Path=Gebertyp}" />
<TextBox Visibility="{Binding ElementName=CmbPWMTyp,Path=SelectedValue,Converter={StaticResource YourConverter},ConverterParameter=TBX}" Text="{Binding GeberNmr,Mode=TwoWay}"/>
<Slider   Visibility="{Binding ElementName=CmbPWMTyp,ConverterParameter=SLDR}" Value="{Binding Wert,Mode=TwoWay}"/>

此链接对您也很有帮助:Difference between SelectedItem SelectedValue and SelectedValuePath