Silverlight MVVM, stop SelectionChanged triggering in response to ItemsSource reset

孤街醉人 提交于 2019-12-08 12:45:36

Why does ComboB need a SelectionChanged event? You can just bind the selected item directly into a property on the VM.

The way i have tackled this previously was to bind ComboA's selected item into the VM. In the setter for that property, i recalculate the available items for ComboB and assign them to another property on the VM, and ComboB's ItemsSource is bound to this property. Of course that property will notify (using INotifyPropertyChanged), but nothing else needed to be done, my ComboB did not have a SelectionChanged event. By using this method i didn't need a SelectionChanged on ComboA either, which keeps the view's code behind nice and sparse - everything is handled in the VM and regular databinding takes care of the rest.

Edit:

Here is an example of adjusting the required lists from within the property setters:

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

And here is a slightly different way to do it, using a PropertyChange event handler on the VM, this simply changes where the list updating happens. This is arguably a better way of doing it than the first sample as it means the property setters don't have side effects:

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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!