WPF ComboBox如何防止代码选择项触发事件

3

我已经在EDIT 2中重新表述了我的问题

大家好,我在WPF中有一个组合框。当我设置SelectedIndex属性时,它会触发SelectionChanged事件,这是正确的行为。但是我想让ComboBox在我以编程方式设置SelectedIndex属性时不触发事件。有办法做到吗?

我正在使用.Net 4.5

EDIT 1: 代码

public void AddLocation()
{
    List<String> locations = new List<String>();

    //LocationBox is the name of ComboBox
    LocationBox.ItemsSource = locations;

    locations.Add("L1");
    locations.Add("B1");
    locations.Add("B3");
    LocationBox.SelectedIndex = 2; //<-- do not want to raise SelectionChanged event programmatically here
    locations.Add("G1");
    locations.Add("G2");
    locations.Add("F1");
    locations.Add("F3");
}

private void LocationBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Console.WriteLine(LocationBox.SelectedIndex);
}

编辑2:重新表述问题

我想在ComboBox中静默选择一个项目,即在没有用户交互的情况下(使用代码/以编程方式),这样它就不会触发SelectionChanged事件。我该怎么做?


当您选择特定索引时,希望ComboBox不起作用吗? - HighEndGuy
当我通过编程方式选择特定的索引时,ComboBox会触发SelectionChanged事件。但在我的代码中,有一种情况我不希望它触发该事件。另一方面,当用户与ComboBox交互时,它应该触发SelectionChanged事件。 - huber.duber
火?我不明白...如果你能用易懂的话解释一下,我可以帮助你 :) 你应该上传你的源代码。 - HighEndGuy
Fire是Raise的同义词。触发一个事件意味着引发一个事件。我已经添加了源代码以方便您使用。 - huber.duber
好的...当特定事件发生时,您无法“停止”事件触发。您可以选择的是设置一个标志,例如IsIgnore = true; => Locationbox.SeletedIndex = 2; => IsIgnore = false; ...然后在SlectionChanged事件处理程序中,如果IsIgnore == true,则什么也不做,直接返回即可。 - cscmh99
显示剩余3条评论
2个回答

2

本答案的注意事项:

  • 这是一种hackish的方法。
  • 这是不良的做法。

我想你可能正在修改现有代码(或者还有其他原因),鉴于示例代码,您可以通过以下代码实现您想要的结果:

// Remove the handler
LocationBox.SelectionChanged -= LocationBox_SelectionChanged;
// Make a selection...
LocationBox.SelectedIndex = 2; //<-- do not want to raise SelectionChanged event programmatically here
// Add the handler again.
LocationBox.SelectionChanged += LocationBox_SelectionChanged;

刚刚在上面回答了你的问题。 - huber.duber
我其实也有同样的想法,即删除和添加处理程序,但我有点不愿意采用这种方法。 - huber.duber
如果你有处理程序,当你进行选择时,不可能不出现if raised。我想这就是它的设计方式。根据你对我上面问题的回答,我认为你可以在VM级别实现它而不是在View级别。但我认为这需要另一个问题。 - tgpdyk
由于时间限制,我会采用这种方法。 - huber.duber
相比于你的结果,我更倾向于使用IsInitializing标志来包装SelectedIndex设置。我猜这是同样的hack但影响较小。 - cscmh99

0
我的猜测是您正在尝试在初始化组合框时不触发事件。您可以使用数据绑定来实现这一点。下面有一个示例,但您可以搜索MVVM模式以获取更多详细信息。
XAML:
<ComboBox ItemsSource="{Binding CBItems}"
          SelectedIndex="{Binding SelectedCBItem}" />

CS:

public class ModelExample : INotfyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private int selectedCBItem;
    public int SelectedCBItem
    {
        get { return selectedCBItem; }
        set
        {
            selectedCBItem = value;
            NotifyPropertyChanged(nameof(SelectedCBItem));
        }
    }

    private List<ComboBoxItem> cbItems;
    public List<ComboBoxItem> CBItems
    {
        get { return cbItems; }
        set
        {
            cbItems= value;
            NotifyPropertyChanged(nameof(CBItems));
        }
    }

    private void NotifyPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class ExampleWindow
{
    ...

    private ModelExample Model;

    private void Initialize()
    {
        ...
        this.DataContext = Model = new ModelExample();

        List<ComboBoxItem> items = // initialize your items somehow
        items.Add(new ComboBoxItem() { Content = "dummy item 1" });
        items.Add(new ComboBoxItem() { Content = "dummy item 2" });

        Model.CBItems = items;
        Model.SelectedCBItem = 1;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接