[英]Cannot update subitems ListBox
我有兩個ListBox
。 一個ListBox
顯示一些項目。 每個項目都有一個子項目列表。 第二個ListBox
顯示第一個ListBox
中當前項的子項。 典型的項目/子項目場景。 當我向子項列表添加一個值時,我無法讓第二個ListBox
更新。 如何強制第二個ListBox
更新我的子項?
我的簡化 XAML 和視圖 model 如下。 請注意,我的觀點 model 繼承自 Prism 的BindableBase
。 在我看來 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>
問題是您的Item
類型包含一個List<int>
,它不會通知集合更改,因為它沒有實現INotifyCollectionChanged
接口。 因此,當集合被修改時,綁定不會在用戶界面中收到更新其值的通知。 使用實現此接口的集合,例如ObservableCollection<int>
將解決該問題。
順便說一句,這同樣適用於ItemValue
和SubItems
屬性以及INotifyPropertyChanged
。 這兩個屬性都有設置器,這意味着它們可以被重新分配,但綁定也不會得到通知。 由於您使用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);
}
}
關於您的項目的評論。 您嘗試做的是分層數據的主從視圖。 由於您已經公開了ICollectionView
,因此您不必顯式使用CurrentItem
。
當源是集合視圖時,可以用斜杠 (/) 指定當前項。 例如,子句 Path=/ 將綁定設置為視圖中的當前項。 當源是集合時,此語法指定默認集合視圖的當前項。
有一種特殊的綁定語法,您可以在其中使用/
來指示當前項,例如:
<ListBox Grid.Row="1" Name="SubItems" ItemsSource="{Binding Items/SubItems}">
另外,關於您查看 model 代碼的一些評論。
_items
字段初始值設定項是無用的,因為無論如何您都在構造函數中重新分配了該字段。_items
,則可以在構造函數中使用局部變量。Items
的私有 setter,您可以將其移除。Items.CurrentItem
直接轉換為Item
以獲得一個無效的轉換異常,該異常比 null 引用異常更具體,您稍后在訪問使用as
和獲取null
的值時會得到該異常。 如果您希望該值可能不是Item
,您可以在as
之后檢查null
或使用模式匹配來適當地處理成功和錯誤這兩種情況( CurrentItem
不是Item
類型)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.