c# - 当项目名称相同时,防止 ComboBox 触发 SelectionChanged 事件?

标签 c# wpf xaml mvvm combobox

我有 2 ComboBoxes数字颜色

数字 ComboBox选择将更改 Item Source 颜色 ComboBox .


问题:

我想防止颜色 ComboBox从发射 SelectionChanged如果新选择的项目与前一个项目具有相同的名称,例如 Item Source 1 中的“红色”,则事件和 Item Source 2 中的“红色” .


数字组合框

ComboBox更改 Item Source 颜色 ComboBox .

<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;
    }
}

列出字符串项目源

不触发 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"
};

列出类项源(问题)

触发 SelectionChanged 事件

我想使用这个自定义 class List<ViewModel.MyColors>对于 Item Source ,所以我可以绑定(bind)多个值,但它会触发 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"}
};

View 模型

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 事件,但会忽略触发时通常会运行的代码,因为我将该代码移到了 ViewModel SelectedItem 绑定(bind)的 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();
    }
}

View 模型

// 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
        }

    }
}

关于c# - 当项目名称相同时,防止 ComboBox 触发 SelectionChanged 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55086189/

相关文章:

c# - XamlReader 和变音符号

wpf - 如何在方形按钮中拉伸(stretch)文本?

c# - WPF:使用虚拟键盘

c# - 随机 HTTP 错误 403.14 - 禁止

c# - 变量的绑定(bind)与显式赋值

c# - 带有超链接的 WPF Resources.resx 字符串?

html - 带有页眉和页脚并调整中间大小的 Css 网格?

c# - FluentAssertions 因带有枚举但不是类的结构而失败

c# - WCF,BasicHttpBinding : Stop new connections but allow existing connections to continue

c# - 在一个 ASP.NET MVC 5 解决方案中拥有单独的项目