【问题标题】:How to prevent combobox SelectionChanged event on binding time (WPf)?如何在绑定时间(WPf)上防止组合框 SelectionChanged 事件?
【发布时间】:2019-03-13 18:28:44
【问题描述】:

在我的 wpf 应用程序组合框中,SelectionChanged 事件在绑定时触发,如何解决?

<telerik:RadComboBox 
    StaysOpenOnEdit="True"
    IsSynchronizedWithCurrentItem="True"
    OpenDropDownOnFocus="True"
    ItemsSource="{Binding SiteSurveyModel.AtsNumberCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
    IsFilteringEnabled="False"
    IsEditable="False">
    <ie:Interaction.Triggers>
        <ie:EventTrigger EventName="SelectionChanged">
            <ie:InvokeCommandAction Command="{Binding ATSRadComboBoxSelectedItemChangedCommand}" CommandParameter="{Binding ElementName=atsRadComboBox}" >
            </ie:InvokeCommandAction>
        </ie:EventTrigger>
    </ie:Interaction.Triggers>
</telerik:RadComboBox>

还有

private void BindAtsNumberCollection()
{
    try
    {
        List<int> NumberList = new List<int>();
        for (int i = 1; i <= 100; i++)
        {
            NumberList.Add(i);
        }
        SiteSurveyModel.AtsNumberCollection = new ObservableCollectionEx<int>(NumberList);
    }
    catch (Exception ex)
    {
      customerAC.LogFile(ex.ToString());
    }
}

和Selection的变化方法是一样的

private void onATSRadComboBoxSelectedItemChangedCommand(object obj)
{
    try
    {
        RadComboBox atsRadComboBox = obj as RadComboBox;
         string  selectedValue= atsRadComboBox.SelectedValue.ToString();
         if (selectedValue.Trim() != string.Empty)
         {
             BindAtsData(Convert.ToInt32(selectedValue));
         }
    }
    catch (Exception ex)
    {
        customerAC.LogFile(ex.ToString());
    }
}

我们正在执行一些计算,当它在加载时间触发时,结果会出错,我们非常沮丧如何解决这个问题。请提供需要的完整解决方案。

【问题讨论】:

  • 它正在发生变化,因此阻止更改事件听起来像是您想隐藏源自不同部分的问题。
  • 嗨 grek40,你明白我的问题吗?当页面打开然后事件触发时,我不想这样。有什么解决办法吗?
  • 事件是在没有实际更改选择的情况下触发,还是在绑定时更改了选择?这是两个完全不同的事情,最后您可能必须更新您的处理程序代码,因为在不派生您自己的自定义控件的情况下可能无法阻止事件触发。或者,如果可能,请考虑其他组件依赖于要触发的事件的可能性。不保证您是唯一的听众。
  • “事件是否在没有实际更改选择的情况下触发” 是。你想看选择更改事件的代码吗?
  • 如果您想要关于如何更改代码的建议,那么我可能必须看到它。但是,这应该不难,只需检查 SelectionChangedEventArgs.AddedItemsSelectionChangedEventArgs.RemovedItems 集合,如果两者都为空,则从处理程序返回。

标签: c# wpf


【解决方案1】:

检查以下条件对我有用,

e.RemovedItems.Count == 0

加载绑定时此计数为 0。

【讨论】:

    【解决方案2】:

    由于您不使用SelectedValuePath,我建议使用SelectedItem 而不是SelectedValue

    无论如何,如果没有选择任何项目,我希望SelectedValuenull,它应该在atsRadComboBox.SelectedValue.ToString() 行拧紧。因此,您需要一种处理“取消选择”的方法,或者至少是一个简单的null 检查,它取消处理程序,而不是尝试ToString 和绑定。

    private void onATSRadComboBoxSelectedItemChangedCommand(object obj)
    {
        try
        {
            RadComboBox atsRadComboBox = obj as RadComboBox;
            if (atsRadComboBox.SelectedValue == null) return;
            string  selectedValue= atsRadComboBox.SelectedValue.ToString();
            if (selectedValue.Trim() != string.Empty)
            {
                BindAtsData(Convert.ToInt32(selectedValue));
            }
        }
        catch (Exception ex)
        {
            customerAC.LogFile(ex.ToString());
        }
    }
    

    如果您对最小的更改感兴趣,这应该已经可以解决问题了。

    更一般地说,您似乎可以引入 viewmodel 属性

    private int? _selectedNumber
    public int? SelectedNumber
    {
        get { return _selectedNumber; }
        set
        {
            _selectedNumber = value;
            NotifyPropertyChanged("SelectedNumber");
            if (_selectedNumber.HasValue) BindAtsData(_selectedNumber.Value);
            else { /* some kind of de-select needed? */ }
        }
    }
    

    通过将此属性直接绑定到RadComboBox.SelectedItem,就不需要整个Interaction - EventTrigger 解决方法。另外,老实说,我不明白为什么SiteSurveyModel.AtsNumberCollection 会是双向的。考虑改为单向。

    <telerik:RadComboBox
        Grid.Row="0" Grid.Column="1"
        Name="atsRadComboBox"
        Width="150" Height="30" MaxHeight="30" MinHeight="30"
        Margin="5,0,0,0"
        HorizontalAlignment="Left" VerticalAlignment="Top"
        StaysOpenOnEdit="True"
        OpenDropDownOnFocus="True"
        IsSynchronizedWithCurrentItem="True"
        ItemsSource="{Binding SiteSurveyModel.AtsNumberCollection}"
        SelectedItem={Binding SelectedNumber,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}
        IsFilteringEnabled="False"
        IsEditable="False"
        IsTextSearchCaseSensitive="False"
        TextSearchMode="Contains"/>
    

    附带说明:如何替换

    List<int> NumberList = new List<int>();
    for (int i = 1; i <= 100; i++)
    {
        NumberList.Add(i);
    }
    SiteSurveyModel.AtsNumberCollection = new ObservableCollectionEx<int>(NumberList);
    

    SiteSurveyModel.AtsNumberCollection = new ObservableCollectionEx<int>(Enumerable.Range(1, 100));
    // or if you absolutely need a `List<int>`
    SiteSurveyModel.AtsNumberCollection = new ObservableCollectionEx<int>(Enumerable.Range(1, 100).ToList());
    

    代码少了一点。

    【讨论】:

    • 你说得对,我可以返回,但是当我们得到 null 时,在我的情况下,我们得到 '1' 作为选定值,请提供更相关的解决方案。
    • @MatthewSiddle 请提供更多相关信息,然后我可以再看一下。但我不知道您对 “当我们得到 null 时我们得到 1 作为选定值”的意思
    • 我是说'我们在绑定时间得到 1 作为选定值而不是 null'。所以这种方法在我的情况下是错误的。 if (atsRadComboBox.SelectedValue == null) return;
    • @MatthewSiddle 停下来!正如我之前问的:“事件是否在没有实际更改选择的情况下触发”,您回答:“是”。现在你来告诉我SelectedValue1 这么清楚,选中的项目确实发生了变化。收集事实,使用Snoop 之类的工具。 Stackoverflow 不是调试站点,也不是解决问题的专业站点。如果你问错了问题,你会得到不合适的答案,这就是这个故事的全部内容。
    • @MatthewSiddle 我还有另一个想法:设置IsSynchronizedWithCurrentItem="False" 而不是True,除非您实际与CollectionView.CurrentItem 交互。这很可能是绑定后具有初始选定项的原因。
    【解决方案3】:

    要解决防止火灾ComboBox.SelectionChanged,在SelectionChanged 事件中,使用Row.RowState=DataRowState.Modified 知道您是否必须做某事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多