[英]Cannot update subitems ListBox
I have two ListBox
es.我有两个
ListBox
。 One ListBox
displays some items.一个
ListBox
显示一些项目。 Each item has a list of subitems.每个项目都有一个子项目列表。 The second
ListBox
displays the subitems of the current item in the first ListBox
.第二个
ListBox
显示第一个ListBox
中当前项的子项。 A typical item/subitem scenario.典型的项目/子项目场景。 When I add a value to the subitem list, I cannot get the second
ListBox
to update.当我向子项列表添加一个值时,我无法让第二个
ListBox
更新。 How can I force the second ListBox
to update my subitems?如何强制第二个
ListBox
更新我的子项?
My simplified XAML and view model are below.我的简化 XAML 和视图 model 如下。 Note that my view model inherits from Prism's
BindableBase
.请注意,我的观点 model 继承自 Prism 的
BindableBase
。 In my view model I have a method to add a value to the subitems list and update the Items
property with RaisePropertyChanged
.在我看来 model 我有一种方法可以将值添加到子项列表并使用
RaisePropertyChanged
更新Items
属性。
<ListBox Name="Items" ItemsSource="{Binding Items}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding ItemValue, Mode=TwoWay}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="SubItems" ItemsSource="{Binding Items.CurrentItem.SubItems}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
class Item
{
public int ItemValue { get; set; }
public List<int> SubItems { get; set; }
}
class MyViewModel : BindableBase
{
private ObservableCollection<Item> _items = new ObservableCollection<Item>();
public MyViewModel()
{
List<Item> myItems = new List<Item>() { /* a bunch of items */ };
_items = new ObservableCollection<Item>(myItems);
Items = new ListCollectionView(_items);
}
public ICollectionView Items { get; private set; }
private void AddNewSubItem(object obj)
{
Item currentItem = Items.CurrentItem as Item;
currentItem.SubItems.Add(123);
RaisePropertyChanged("Items");
}
}
class Item
{
public int ItemValue { get; set; }
public ObservableCollection<int> SubItems { get;}
= new ObservableCollection<int>();
}
class MyViewModel : BindableBase
{
publc ObservableCollection<Item> Items {get;}
= new ObservableCollection<Item>();
public MyViewModel()
{
List<Item> myItems = new List<Item>() { /* a bunch of items */ };
myItems.ForEach(item => Items.Add(item));
}
private Item _currentItem;
private Item CurrentItem
{
get => _currentItem;
set
{
if(Equals(_currentItem, value))
return;
_currentItem = value;
RaisePropertyChanged(nameof(CurrentItem));
}
}
private void AddNewSubItem(object obj)
{
CurrentItem.SubItems.Add(123);
}
}
<ListBox ItemsSource="{Binding Items}"
SelectedItem="{Binding CurrentItem}">
********
********
</ListBox>
<ListBox ItemsSource="{Binding CurrentItem.SubItems}" >
********
********
</ListBox>
The issue is that your Item
type contains a List<int>
, which does not notify on collection changes, because it does not implement the INotifyCollectionChanged
interface.问题是您的
Item
类型包含一个List<int>
,它不会通知集合更改,因为它没有实现INotifyCollectionChanged
接口。 Consequently, bindings do not get notified to update their values in the user interface when the collection is modified.因此,当集合被修改时,绑定不会在用户界面中收到更新其值的通知。 Using a collection that implements this interface, eg an
ObservableCollection<int>
will solve the issue.使用实现此接口的集合,例如
ObservableCollection<int>
将解决该问题。
By the way, the same applies to ItemValue
and SubItems
properties as well with INotifyPropertyChanged
.顺便说一句,这同样适用于
ItemValue
和SubItems
属性以及INotifyPropertyChanged
。 Both properties have setters, which means they can be reassigned, but the bindings will not get notified then either.这两个属性都有设置器,这意味着它们可以被重新分配,但绑定也不会得到通知。 Since you use
BindableBase
, you can use the SetProperty
method with backing fields to automatically raise the PropertyChanged
event when a property is set.由于您使用
BindableBase
,因此您可以使用带有支持字段的SetProperty
方法在设置属性时自动引发PropertyChanged
事件。
public class Item : BindableBase
{
private int _itemValue;
private ObservableCollection<int> _subItems;
public int ItemValue
{
get => _itemValue;
set => SetProperty(ref _itemValue, value);
}
public ObservableCollection<int> SubItems
{
get => _subItems;
set => SetProperty(ref _subItems, value);
}
}
A remark about your project.关于您的项目的评论。 What you try to do is a master-detail view for hierarchical data .
您尝试做的是分层数据的主从视图。 Since you already expose an
ICollectionView
, you do not have to use the CurrentItem
explicitly.由于您已经公开了
ICollectionView
,因此您不必显式使用CurrentItem
。
When the source is a collection view, the current item can be specified with a slash (/).
当源是集合视图时,可以用斜杠 (/) 指定当前项。 For example, the clause Path=/ sets the binding to the current item in the view.
例如,子句 Path=/ 将绑定设置为视图中的当前项。 When the source is a collection, this syntax specifies the current item of the default collection view.
当源是集合时,此语法指定默认集合视图的当前项。
There is a special binding syntax, where you can use a /
to indicate the current item, eg:有一种特殊的绑定语法,您可以在其中使用
/
来指示当前项,例如:
<ListBox Grid.Row="1" Name="SubItems" ItemsSource="{Binding Items/SubItems}">
Additionally a few remarks about your view model code.另外,关于您查看 model 代码的一些评论。
_items
field initializer is useless, as you reassign the field in the constructor anyway. _items
字段初始值设定项是无用的,因为无论如何您都在构造函数中重新分配了该字段。_items
, you can use a local variable in the constructor._items
,则可以在构造函数中使用局部变量。Items
is not used, you can remove it.Items
的私有 setter,您可以将其移除。Items.CurrentItem
directly to Item
to get an invalid cast exception that is more specific that the null reference exception that you would get later when accessing the value from using as
and getting null
.Items.CurrentItem
直接转换为Item
以获得一个无效的转换异常,该异常比 null 引用异常更具体,您稍后在访问使用as
和获取null
的值时会得到该异常。 If you expect that the value could be something else than an Item
, you could check for null
after as
or use pattern matching to handle both cases, success and error ( CurrentItem
is not of type Item
) appropriately.Item
,您可以在as
之后检查null
或使用模式匹配来适当地处理成功和错误这两种情况( CurrentItem
不是Item
类型)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.