Dav*_*can 12 c# wpf observablecollection mvvm
我刚开始使用MVVM并遇到了障碍,我希望有人可以帮助我.我正在尝试使用2个列表框创建一个简单的视图.第一个列表框中的选择将填充第二个列表框.我创建了一个类,用于存储我想要绑定的信息.
MyObject类(Observable Object只是一个实现INotifyPopertyChanged的基类)
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>();
}
}
Run Code Online (Sandbox Code Playgroud)
在我的viewmodel中,我创建了两个ObservableCollections
public ObservableCollection<EMSMenuItem> Level1MenuItems { get; set; }
public ObservableCollection<EMSMenuItem> Level2MenuItems { get; set; }
Run Code Online (Sandbox Code Playgroud)
在我的ViewModel的构造函数中,我有:
this.Level1MenuItems = new ObservableCollection<EMSMenuItem>();
this.Level2MenuItems = new ObservableCollection<EMSMenuItem>();
this.Level1MenuItems = LoadEMSMenuItems("Sample.Xml");
Run Code Online (Sandbox Code Playgroud)
这适用于Level1项目,它们在视图中正确显示.但是,当用户单击列表框中的项目时,我会调用一个命令,该命令具有以下内容:
Level2MenuItems = ClickedItem.SubCategories;
Run Code Online (Sandbox Code Playgroud)
由于某种原因,这不会更新第二个列表框的UI.如果我在这个位置放置一个断点,我可以看到Level2MenuItems中存储了正确的信息.如果我编写一个foreach循环并将它们单独添加到Level2MenuItems集合中,那么它会正确显示.
另外作为测试,我将以下内容添加到构造函数中:
Level2MenuItems = Level1MenuItems[0].SubCategories;
Run Code Online (Sandbox Code Playgroud)
而且更新正确.
那么为什么代码在构造函数中按预期工作,或者在循环时,而不是在用户单击列表框中的项目时?
aqw*_*ert 12
您需要在Level2MenuItems属性上提出更改通知.
而不是拥有
public ObservableCollection<EMSMenuItem> Level2MenuItems { get; set; }
Run Code Online (Sandbox Code Playgroud)
你需要
private ObservableCollection<EMSMenuItem> _level2MenuItems;
public ObservableCollection<EMSMenuItem> Level2MenuItems
{
get { return _level2MenuItems; }
set
{
_level2MenuItems = value;
RaisePropertyChanged("Level2MenuItems");
}
}
Run Code Online (Sandbox Code Playgroud)
前者在构造函数中工作的原因是Binding还没有发生.但是,由于您通过命令执行更改引用,这在绑定之后发生,您需要告诉视图它已更改
您需要使 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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17979 次 |
| 最近记录: |