silverlight-4.0 - Silverlight MVVM,停止 SelectionChanged 触发以响应 ItemsSource 重置

标签 silverlight-4.0 mvvm combobox inotifypropertychanged selectionchanged

我有两个组合框,A 和 B,每个都绑定(bind)到一个 Observable 集合。每个都附加了一个 SelectionChanged 触发器,用于在用户更改选择时捕获。触发器将选择传递给命令。

这些集合实现了 INotifyPropertyChanged,因为在每个集合的 Setter 中,都会触发一个 NotifyPropertyChanged 事件。这需要(在 MVVM 方法中)通知 UI( View )ComboBox 的内容已更改。

这两个 ComboBox 是相互依赖的 - 更改 A 中的选择会导致 B 重新填充新项目。

现在,问题是 B 的 SelectionChanged 触发器响应其集合被重新填充(以及用户更改选择)而触发。由于命令中代码的复杂性,这是对资源的巨大浪费。

理论上我可以通过在设置 B 的集合时不引发 NotifyPropertyChanged 事件来阻止这种情况(因为,查看调用堆栈,这似乎是导致 SelectionChanged 触发器触发的原因),但是 MVVM 方法依赖于此来保持 UI神清气爽。

有什么建议么?

最佳答案

为什么 ComboB 需要 SelectionChanged 事件?您可以将所选项目直接绑定(bind)到 VM 上的属性中。

我之前解决这个问题的方法是将 ComboA 的选定项目绑定(bind)到 VM 中。在该属性的 setter 中,我重新计算了 ComboB 的可用项并将它们分配给 VM 上的另一个属性,并且 ComboB 的 ItemsSource 绑定(bind)到此属性。当然,该属性会通知(使用 INotifyPropertyChanged),但无需执行任何其他操作,我的 ComboB 没有 SelectionChanged 事件。通过使用这种方法,我也不需要在 ComboA 上使用 SelectionChanged,它使 View 的代码保持良好和稀疏 - 一切都在 VM 中处理,常规数据绑定(bind)负责其余部分。

编辑:

这是从属性 setter 中调整所需列表的示例:

public class MyViewModel : INotifyPropertyChanged
{

    //ItemsSource of ComboA is bound to this list
    public List<SomeObject> ComboAList
    {
        get { return _comboAList; }
        set { _comboAList = value; }
    }

    //ItemsSource of ComboB is bound to this list
    public List<SomeObject> ComboBList
    {
        get { return _comboBList; }
        set 
        {
            _comboBList = value;
            OnPropertyChanged("ComboBList");
        }
    }

    //ItemsSource of the dataGrid is bound to this list
    public List<SomeObject> DataGridList
    {
        get { return _datagridList; }
        set
        {
            _datagridList = value;
            OnPropertyChanged("DataGridList");
        }
    }

    //SelectedItem of ComboA is bound to this property
    public SomeObject FirstSelectedItem
    {
        get { return _firstSelectedItem; }
        set
        {
            _firstSelectedItem = value;
            RefreshListForComboB();
        }
    }

    //SelectedItem of ComboB is bound to this property
    public SomeObject SecondSelectedItem
    {
        get { return _secondSelectedItem; }
        set
        {
            _secondSelectedItem = value;
            RefreshListForDataGrid();
        }
    }



    private void RefreshListForComboB()
    {
        //do whatever is necessary to filter or create a list for comboB
        ComboBList = doSomethingThatReturnsAListForComboB();
    }

    private void RefreshListForDataGrid()
    {
        //do whatever is necessary to filter or create the list for the DataGrid
        DataGridList = doSomethingThatReturnsAListForDataGrid();
    }


    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion


    private List<SomeObject> _comboAList, _comboBList, _datagridList;
    private SomeObject _firstSelectedItem, _secondSelectedItem;
}

这是一种稍微不同的方法,在 VM 上使用 PropertyChange 事件处理程序,这只是更改列表更新发生的位置。这可以说是比第一个示例更好的方法,因为这意味着属性 setter 没有副作用:
public class MyViewModel : INotifyPropertyChanged
{

    public MyViewModel()
    {
        this.PropertyChanged += new PropertyChangedEventHandler(MyViewModel_PropertyChanged);
    }

    private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "FirstSelectedItem":
                RefreshListForComboB();
                break;

            case "SecondSelectedItem":
                RefreshListForDataGrid();
                break;
        }
    }

    //ItemsSource of ComboA is bound to this list
    public List<SomeObject> ComboAList
    {
        get { return _comboAList; }
        set { _comboAList = value; }
    }

    //ItemsSource of ComboB is bound to this list
    public List<SomeObject> ComboBList
    {
        get { return _comboBList; }
        set 
        {
            _comboBList = value;
            OnPropertyChanged("ComboBList");
        }
    }

    //ItemsSource of the dataGrid is bound to this list
    public List<SomeObject> DataGridList
    {
        get { return _datagridList; }
        set
        {
            _datagridList = value;
            OnPropertyChanged("DataGridList");
        }
    }

    //SelectedItem of ComboA is bound to this property
    public SomeObject FirstSelectedItem
    {
        get { return _firstSelectedItem; }
        set
        {
            _firstSelectedItem = value;
            OnPropertyChanged("FirstSelectedItem");
        }
    }

    //SelectedItem of ComboB is bound to this property
    public SomeObject SecondSelectedItem
    {
        get { return _secondSelectedItem; }
        set
        {
            _secondSelectedItem = value;
            OnPropertyChanged("SecondSelectedItem");
        }
    }



    private void RefreshListForComboB()
    {
        //do whatever is necessary to filter or create a list for comboB
        ComboBList = doSomethingThatReturnsAListForComboB();
    }

    private void RefreshListForDataGrid()
    {
        //do whatever is necessary to filter or create the list for the DataGrid
        DataGridList = doSomethingThatReturnsAListForDataGrid();
    }


    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion


    private List<SomeObject> _comboAList, _comboBList, _datagridList;
    private SomeObject _firstSelectedItem, _secondSelectedItem;
}

关于silverlight-4.0 - Silverlight MVVM,停止 SelectionChanged 触发以响应 ItemsSource 重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6265107/

相关文章:

c# - .NET CF 为组合框设置 'DroppedDown'

JavaFX 组合框图像

mvvm - Kendo UI - 您可以将 View 模型创建为函数吗

c# - 带有 MVVM 和 DataAnnotations 的 WPF,UserControl 中的验证错误

c# - 使用 mvvm 和 wpf 重用菜单

data-binding - Silverlight 4 外观控制。绑定(bind)到同一控件中的另一个元素

python - ttk.组合框 : How to place a default text inside the box?

silverlight - 在 Silverlight 4 中托管 Microsoft Office 应用程序?

c# - 使自动生成的部分类实现自定义接口(interface)

Silverlight 4 支持 x :TypeArguments