ObservableCollectionが更新されないビュー

私はMVVMを使い始めており、誰かが私を助けてくれることを願っています。私は2つのリストボックスで簡単なビューを作成しようとしています。最初のリストボックスから選択すると、2番目のリストボックスが表示されます。私はバインドしたい情報を保存するクラスを作成しました。

MyObjectクラス(ObservableオブジェクトはINotifyPopertyChangedを実装する単なる基本クラスです)

public class MyObject : ObservableObject
{
    String _name = String.Empty;
    ObservableCollection _subcategories;

    public ObservableCollection SubCategories
    {
        get { return _subcategories; }

        set
        {
            _subcategories = value;
            RaisePropertyChanged("SubCategories");
        }
    }

    public String Name
    {
        get { return _name; }
        set
        {
            _name = value;
            RaisePropertyChanged("Name");
        }
    }


    public MyObject()
    {
        _subcategories = new ObservableCollection();
    }
}

私のビューモデルでは、2つのObservableCollectionが作成されています

public ObservableCollection Level1MenuItems { get; set; }
public ObservableCollection Level2MenuItems { get; set; }

ViewModelの私のコンストラクタで私は持っている:

this.Level1MenuItems = new ObservableCollection();
this.Level2MenuItems = new ObservableCollection();
this.Level1MenuItems = LoadEMSMenuItems("Sample.Xml");

レベル1の項目は正常に動作し、表示に正しく表示されます。しかし、私は、ユーザーがリストボックス内の項目をクリックすると呼び出されるコマンドを持っています。

Level2MenuItems = ClickedItem.SubCategories;

何らかの理由で、これは2番目のリストボックスのUIを更新しません。この場所にブレークポイントを置くと、Level2MenuItemsに正しい情報が格納されていることがわかります。 foreachループを作成してLevel2MenuItemsコレクションに個別に追加すると、正しく表示されます。

また、テストとして私はコンストラクタに以下を追加しました:

Level2MenuItems = Level1MenuItems[0].SubCategories;

そしてそれは正しく更新されました。

だから、なぜコードは、コンストラクタやループスルーで期待どおりに動作しますが、ユーザがリストボックス内の項目をクリックしたときには動作しませんでしたか?

8

3 答え

Level2MenuItems プロパティで変更通知を発行する必要があります。

持っているのではなく

public ObservableCollection Level2MenuItems { get; set; }

あなたが必要です

private ObservableCollection _level2MenuItems;
public ObservableCollection Level2MenuItems
{
    get { return _level2MenuItems; }
    set 
     {
        _level2MenuItems = value; 
        RaisePropertyChanged("Level2MenuItems");
     }
 }

The reason the former works in the constructor is that the Binding has not taken place yet. However since you are changing the reference via a command execute which happens after the binding あなたが必要です to tell view that it changed

7
追加された
ありがとう。正確に私が必要としたもの。
追加された 著者 David Duncan,

ObservableCollection内のpocoクラスをINotifyPropertyChangedにする必要があります。

例:


.
.
.    


    
        
            
                
                
                
            
        
    


public class LocationViewModel : BaseViewModel
{
    ObservableCollection _locations = new ObservableCollection();
    public ObservableCollection Locations
    {
        get
        {
            return _locations;
        }
        set
        {
            if (_locations != value)
            {
                _locations = value;
                OnNotifyPropertyChanged();
            }
        }
    }
}

public class Location : BaseViewModel
{
    int _locationId = 0;
    public int LocationId
    {
        get
        {
            return _locationId;
        }
        set
        {
            if (_locationId != value)
            {
                _locationId = value;
                OnNotifyPropertyChanged();
            }
        }
    }

    string _name = null;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if (_name != value)
            {
                _name = value;
                OnNotifyPropertyChanged();
            }
        }
    }

    float _latitude = 0;
    public float Latitude 
    { 
        get
        {
            return _latitude;
        }
        set
        {
            if (_latitude != value)
            {
                _latitude = value;
                OnNotifyPropertyChanged();
            }
        }
    }

    float _longitude = 0;
    public float Longitude
    {
        get
        {
            return _longitude;
        }
        set
        {
            if (_longitude != value)
            {
                _longitude = value;
                OnNotifyPropertyChanged();
            }
        }
    }
}

public class BaseViewModel : INotifyPropertyChanged
{
    #region Events
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    protected void OnNotifyPropertyChanged([CallerMemberName] string memberName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(memberName));
        }
    }
}
1
追加された

あなたのサブカテゴリプロパティは、読み取り専用にする必要があります

0
追加された
@クリス:私は彼がプロパティを設定していると思われる。
追加された 著者 SLaks,
これはどのように問題に対処していますか?
追加された 著者 ChrisF,