2011-12-18 11 views
8

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

MyObjectにクラスは、私は私が持っている2 ObservableCollectionsはViewModelに私のコンストラクタで

public ObservableCollection<EMSMenuItem> Level1MenuItems { get; set; } 
public ObservableCollection<EMSMenuItem> Level2MenuItems { get; set; } 

を作成している私のviewmodelで

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

    public ObservableCollection<MyObject> 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<EMSMenuItem>(); 
    } 
} 

(被監視オブジェクトはINotifyPopertyChangedを実装だけで、基本クラスである):

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

レベル1の項目で問題ないビューに正しく表示されます。これは2番目のリストボックスのUIを更新していないいくつかの理由について

Level2MenuItems = ClickedItem.SubCategories; 

:しかし、私は、ユーザーが次のように持って、リストボックス内の項目を、クリックしたときに呼び出されるコマンドを持っています。この場所にブレークポイントを置くと、Level2MenuItemsに正しい情報が格納されていることがわかります。 foreachループを作成してLevel2MenuItemsコレクションに個別に追加すると、正しく表示されます。

Level2MenuItems = Level1MenuItems[0].SubCategories; 

そして、それが正しく更新:私は、コンストラクタに以下を追加テストなども

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

答えて

6

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

代わり

public ObservableCollection<EMSMenuItem> Level2MenuItems { get; set; } 

を有しているとあなたは

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

コンストラクタの元の作品はバインディングがまだ行われていないことである理由が必要です。しかし、バインド後に実行されるコマンドの実行で参照を変更しているため、ビューに変更があったことを伝える必要があります。

+0

感謝。正確に私が必要としたもの。 –

0

Subcategoriesプロパティshould be read-only

+0

これはどのように問題に対処していますか? – ChrisF

+0

@ChrisF:私は彼が不動産を設定していると思う。 – SLaks

1

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

例:

<viewModels:LocationsViewModel x:Key="viewModel" /> 
. 
. 
.  
<ListView 
    DataContext="{StaticResource viewModel}" 
    ItemsSource="{Binding Locations}" 
    IsItemClickEnabled="True" 
    ItemClick="GroupSection_ItemClick" 
    ContinuumNavigationTransitionInfo.ExitElementContainer="True"> 

    <ListView.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding Name}" Margin="0,0,10,0" Style="{ThemeResource ListViewItemTextBlockStyle}" /> 
       <TextBlock Text="{Binding Latitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="0,0,5,0"/> 
       <TextBlock Text="{Binding Longitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="5,0,0,0" /> 
      </StackPanel> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

public class LocationViewModel : BaseViewModel 
{ 
    ObservableCollection<Location> _locations = new ObservableCollection<Location>(); 
    public ObservableCollection<Location> 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)); 
     } 
    } 
} 
関連する問題