当项目具有相同名称时,阻止ComboBox触发SelectionChanged事件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当项目具有相同名称时,阻止ComboBox触发SelectionChanged事件?相关的知识,希望对你有一定的参考价值。

我有2个ComboBoxes,数字和颜色。

数字ComboBox选择将改变颜色Item SourceComboBox


问题:

如果新选择的项目与前一项目具有相同的名称,例如ComboBox中的“Red”和SelectionChanged中的“Red”,我想阻止Colors Item Source 1触发Item Source 2事件。


Numbers ComboBox

这个ComboBox改变了颜色Item SourceComboBox

<ComboBox x:Name="cboNumbers"
          SelectedItem="{Binding Numbers_SelectedItem}"
          IsSynchronizedWithCurrentItem="True"
          HorizontalAlignment="Left" 
          Margin="190,55,0,0" 
          VerticalAlignment="Top" 
          Width="120" 
          SelectionChanged="cboNumbers_SelectionChanged"/> 
    <System:String>1</System:String>
    <System:String>2</System:String>
</ComboBox>


// Change Item Source with Selection
//
private void cboNumbers_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (vm.Numbers_SelectedItem == "1")
    {
        vm.Colors_Items = colors1;
    }
    else if (vm.Numbers_SelectedItem == "2")
    {
        vm.Colors_Items = colors2;
    }
}

List String Item Source

不会激活SelectionChanged事件

如果我使用List<string>作为Item Source,并且SelectedItem与前一项相同,它将不会触发ComboBox SelectionChanged事件。

<ComboBox x:Name="cboColors"
          ItemsSource="{Binding Colors_Items}"
          SelectedItem="{Binding Colors_SelectedItem}"
          IsSynchronizedWithCurrentItem="True"
          HorizontalAlignment="Left" 
          Margin="190,55,0,0" 
          VerticalAlignment="Top" 
          Width="120" 
          SelectionChanged="cboColors_SelectionChanged"/>


// Colors Item Source 1
public List<string> colors1 = new List<string>()
{
    "Red",  //<-- same name (doesn't fire event)
    "Green",
    "Blue"
};

// Colors Item Source 2
public List<string> colors2 = new List<string>()
{
    "Red",  //<-- same name (doesn't fire event)
    "Yellow",
    "Purple"
};

List Class Item Source (Problem)

Fires SelectionChanged事件

我想使用这个自定义class List<ViewModel.MyColors>Item Source,所以我可以绑定多个值,但它会触发ComboBox SelectionChanged事件。

<ComboBox x:Name="cboColors"
          ItemsSource="{Binding Colors_Items}"
          SelectedValue="{Binding Colors_SelectedItem}"
          SelectedValuePath="Name"
          IsSynchronizedWithCurrentItem="True"
          HorizontalAlignment="Left" 
          Margin="190,111,0,0" 
          VerticalAlignment="Top" 
          Width="120" 
          SelectionChanged="cboColors_SelectionChanged">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBlock Text="{Binding Name}"></TextBlock>
            </Grid>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>


// Colors Item Source 1
public List<ViewModel.MyColors> colors1 = new List<ViewModel.MyColors>()
{
    new ViewModel.MyColors() { Name = "Red",       Value = "a"}, //<-- same name (fires event)
    new ViewModel.MyColors() { Name = "Green",     Value = "b"},
    new ViewModel.MyColors() { Name = "PuBlueple", Value = "c"}
};

// Colors Item Source 2
public List<ViewModel.MyColors> colors2 = new List<ViewModel.MyColors>()
{
    new ViewModel.MyColors() { Name = "Red",    Value = "x"},    //<-- same name (fires event)
    new ViewModel.MyColors() { Name = "Yellow", Value = "y"},
    new ViewModel.MyColors() { Name = "Purple", Value = "z"}
};

ViewModel

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    private void OnPropertyChanged(string prop)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(prop));
        }
    }

    // Numbers Selected Item
    private string _Numbers_SelectedItem { get; set; }
    public string Numbers_SelectedItem
    {
        get { return _Numbers_SelectedItem; }
        set
        {
            if (_Numbers_SelectedItem == value) { return; }

            _Numbers_SelectedItem = value;
            OnPropertyChanged("Numbers_SelectedItem");
        }
    }

    // Colors Item Source
    public class MyColors
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }
    public List<MyColors> _Colors_Items = new List<MyColors>();
    public List<MyColors> Colors_Items
    {
        get { return _Colors_Items; }
        set
        {
            _Colors_Items = value;
            OnPropertyChanged("Colors_Items");
        }
    }
    // Colors Selected Item
    private string _Colors_SelectedItem { get; set; }
    public string Colors_SelectedItem
    {
        get { return _Colors_SelectedItem; }
        set
        {
            if (_Colors_SelectedItem == value) { return; }

            _Colors_SelectedItem = value;
            OnPropertyChanged("Colors_SelectedItem");
        }
    }
}
答案

这是我正在使用的黑客。它仍会触发SelectionChanged Event,但忽略了它通常会在触发时运行的代码,因为我将该代码移动到ViewModel SelectedItem绑定的String

组合框

public static string colors_PreviousItem;

private void cboColors_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Save the Previous Item
    if (!string.IsNullOrEmpty(vm.Colors_SelectedItem))
    {
        colors_PreviousItem = vm.Colors_SelectedItem;
    }

    // Select Item
    vm.Colors_SelectedItem = SelectItem(vm.Colors_Items.Select(c => c.Name).ToList(),
                                        colors_PreviousItem
                                        );

    // I used to have the code I want to run in here
}


// Select Item Method
//
public static string SelectItem(List<string> itemsName,
                                string selectedItem
                                )
{
    // Select Previous Item
    if (itemsName?.Contains(selectedItem) == true)
    {
        return selectedItem;
    }

    // Default to First Item
    else
    {
        return itemsName.FirstOrDefault();
    }
}

视图模型

// Selected Item
//
private string _Colors_SelectedItem { get; set; }
public string Colors_SelectedItem
{
    get { return _Colors_SelectedItem; }
    set
    {
        var previousItem = _Colors_SelectedItem;
        _Colors_SelectedItem = value;
        OnPropertyChanged("Colors_SelectedItem");

        // Ignore if Previous Item is different than New Item
        if (previousItem != value)
        {
            // Moved the code I want to run in here
            // I want to ignore the code in here when the SelectionChanged Event fires 
            // and the Previous and Newly Selected Items are the same
        }

    }
}

以上是关于当项目具有相同名称时,阻止ComboBox触发SelectionChanged事件?的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止具有相同触发按钮但功能不同的表单提交?

Unity:OnCollisionEnter 仅在新条目时触发,但不会在具有相同名称的不同对象上的新条目时触发

打开 ComboBox 时 KeyDown 事件不起作用?

禁止/阻止选择 wpf 中禁用的组合框项目

XAML 组合框 SelectionChanged 触发 OnLoad

当参数具有相同名称时如何恢复内置函数?