我有ObservableCollection<UsageItem> MyItems;
:
编辑:
public class UsageItem : INotifyPropertyChanged
{
string _Name;
public string Name
{
get
{
return _Name;
}
set
{
if (_Name != value)
{
_Name = value;
RaisePropertyChanged("Name");
}
}
}
int _ChargesLeft;
public int ChargesLeft
{
get
{
return _ChargesLeft;
}
protected set
{
if (_ChargesLeft != value)
{
_ChargesLeft = value;
RaisePropertyChanged("ChargesLeft");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
}
public Consummable(string name, int charges)
{
this.Name = name;
this.ChargesLeft = charges;
}
public override string DisplayName
{
get
{
if (ChargesLeft > 1)
{
return Name + " " + ChargesLeft + "charges";
}
else
{
return Name + " " + ChargesLeft + "charge";
}
}
}
public override void use(Hero hero)
{
if(this.ChargesLeft >= 1)
{
this.ChargesLeft--;
}else{
//Will remove this UsageItem from my ObservableCollection
...
}
}
}
我已将Collection
绑定到ListBox
:
<ListBox x:Name="listBoxBackPack" ItemsSource="{Binding MyItems}" SelectedItem="{Binding SelectedItem}" DisplayMemberPath="DisplayName"/>
我有一个按钮,当点击时调用use
上的SelectedItem
函数,它会减小我的ChargesLeft字段值或删除对象。
如果我在ChargesLeft值为&lt; = 1时单击该按钮,它将从我的Collection中删除我的Item,我的ListBox将按预期更新,没问题。
但是如果我使用带有ChargesLeft&gt; = 1的项目,那么我将减少我的字段,从而改变我的DisplayName。
当我仍然更改我的收藏时,我希望触发CollectionChanged
事件并刷新我的列表框并显示该项目的新DisplayValue
,但不会发生,ListBox
保持不变显示旧的DisplayValue
此时如果我手动执行Listbox.Items.Refresh()
(在按钮上将其绑定以进行测试),它将刷新并正确显示正确的DisplayValue
,但我无法从我的{{1}调用此函数因为它不了解我的ViewModel
如何在修改项目时自动强制刷新ListBox
?
答案 0 :(得分:2)
CollectionChanged
。您的UsageItem
类需要实现INotifyPropertyChanged
本身来跟踪收集项中的更改。
https://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx
请注意
要完全支持将数据值从绑定源对象传输到绑定目标,集合中支持可绑定属性的每个对象都必须实现适当的属性更改通知机制,例如INotifyPropertyChanged接口。
<强>更新强> 看一个工作实例(我使用Prism,但这并不重要):
<强> UsageItem.cs:强>
public class UsageItem : INotifyPropertyChanged
{
string _Name;
public string Name
{
get
{
return _Name;
}
set
{
if (_Name != value)
{
_Name = value;
RaisePropertyChanged("Name");
RaisePropertyChanged("DisplayName");
}
}
}
int _ChargesLeft;
public int ChargesLeft
{
get
{
return _ChargesLeft;
}
set
{
if (_ChargesLeft != value)
{
_ChargesLeft = value;
RaisePropertyChanged("ChargesLeft");
RaisePropertyChanged("DisplayName");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
}
public UsageItem(string name, int charges)
{
this.Name = name;
this.ChargesLeft = charges;
}
public string DisplayName
{
get
{
if (ChargesLeft > 1)
{
return Name + " " + ChargesLeft + "charges";
}
else
{
return Name + " " + ChargesLeft + "charge";
}
}
}
}
<强> MainViewModel:强>
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Unity Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public MainWindowViewModel()
{
Items = new ObservableCollection<UsageItem>();
Items.Add(new UsageItem("Bob", 1));
Items.Add(new UsageItem("Bill", 2));
Items.Add(new UsageItem("Joe", 3));
CurrentItem = Items[0];
UseCommand = new DelegateCommand(Use);
}
public ObservableCollection<UsageItem> Items { get; private set; }
private UsageItem _currentItem;
public UsageItem CurrentItem
{
get { return _currentItem; }
set { SetProperty(ref _currentItem, value); }
}
public DelegateCommand UseCommand { get; private set; }
private void Use()
{
if (CurrentItem.ChargesLeft >= 1)
{
CurrentItem.ChargesLeft--;
}
else
{
//Will remove this UsageItem from my ObservableCollection
Items.Remove(CurrentItem);
CurrentItem = Items[0];
}
}
}
<强> MainWindow.xaml:强>
<Window x:Class="UsageLeft.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="{Binding Title}"
Width="525"
Height="350"
prism:ViewModelLocator.AutoWireViewModel="True">
<StackPanel>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding CurrentItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Command="{Binding UseCommand}" Content="Use" />
</StackPanel>
</Window>