【问题标题】:Prevent ComboBox from firing SelectionChanged Event when Items have same name?当项目具有相同名称时,防止 ComboBox 触发 SelectionChanged 事件?
【发布时间】:2019-07-31 20:12:52
【问题描述】:

我有 2 个ComboBoxes数字颜色

数字 ComboBox 选择将更改颜色 ComboBoxItem Source


问题:

如果新选择的项目与前一个项目具有相同的名称,例如 Item Source 1 中的“红色”和Item Source 2中的“红色”。


数字组合框

这个ComboBox 改变了颜色 ComboBoxItem Source

<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 事件

如果我对Item Source 使用List&lt;string&gt;,并且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&lt;ViewModel.MyColors&gt; 用于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"}
};

视图模型

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

【问题讨论】:

  • 你找到解决办法了吗?
  • @Avinash 嗨,我还没有找到解决方案。
  • 我遇到了几乎相同的问题
  • @Avinash 我必须创建一个 hack,但我想找到一个更专业的解决方案。如果您想看一下,我会看看是否可以发布代码作为答案。
  • @Avinash 抱歉,实际上那是代码的另一部分。我无法阻止 ComboBox 触发事件。我修改了 VieModel 绑定的SelectedItem 字符串,因此它在触发时会忽略一些代码。然后就跟不着火差不多了。

标签: c# wpf xaml mvvm combobox


【解决方案1】:

这是我正在使用的 hack。它仍然会触发 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
        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 2014-03-26
    • 1970-01-01
    • 2014-05-02
    • 2012-02-03
    • 2016-06-06
    • 2016-11-30
    相关资源
    最近更新 更多