Wpf 与ObservableCollection绑定的列表框未随集合更新
我有下一个型号:Wpf 与ObservableCollection绑定的列表框未随集合更新,wpf,xaml,observablecollection,Wpf,Xaml,Observablecollection,我有下一个型号: public class MyModel { public ObservableCollection<MyObject> MyList {get; set;} } public class MyObject { MyObservableDictionary MyDictionary {get; set;} } public class MyObservableDictionary : ObservableCollection<EnymVal
public class MyModel
{
public ObservableCollection<MyObject> MyList {get; set;}
}
public class MyObject
{
MyObservableDictionary MyDictionary {get; set;}
}
public class MyObservableDictionary : ObservableCollection<EnymValue>
{
}
public class EnymValue : INotifyPropertyChanged
{
private MyEnum key;
private string value;
public MyEnum Key
{
get
{
return this.key;
}
set
{
this.key = value;
NotifyPropertyChanged("Key");
}
}
public string Value
{
get
{
return this.value;
}
set
{
this.value = value;
NotifyPropertyChanged("Value");
}
}
public LanguageValue(MyEnum key, string value)
{
this.Key = key;
this.Value = value;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public enum MyEnum
{
}
公共类MyModel
{
公共ObservableCollection MyList{get;set;}
}
公共类MyObject
{
MyObservableDictionary MyDictionary{get;set;}
}
公共类MyObservableDictionary:ObservableCollection
{
}
公共类EnymValue:INotifyPropertyChanged
{
私钥;
私有字符串值;
公共髓鞘密钥
{
得到
{
返回此.key;
}
设置
{
this.key=值;
NotifyPropertyChanged(“密钥”);
}
}
公共字符串值
{
得到
{
返回此.value;
}
设置
{
这个值=值;
NotifyPropertyChanged(“价值”);
}
}
公共语言值(MyEnum键、字符串值)
{
这个。键=键;
这个。值=值;
}
公共事件属性更改事件处理程序属性更改;
public void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]字符串propertyName=”“)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
公共枚举髓鞘
{
}
在视图中,我有一个列表框:
<ListBox x:Name="MyList" SelectionMode="Single" ItemsSource="{Binding Path=MyList, Mode=OneWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=MyDictionary, Mode=OneWay, Converter={StaticResource myEnumToTextConverter}}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
(myEnumToTextConverter converter只是从集合中选择第一个元素并返回它的值,或者在集合为null或空时返回某个指定的常量)
当任何EnymValue
值发生更改时,我希望在视图中更新模型的列表框。
是否有可能以某种方式实现这一点?
当前,当值
更改时,视图不会更新。
我试图从INotifyPropertyChanged继承
EnymValue
,但这没有帮助。属性更新时,在EnymValue上看起来像PropertyChanged==null
。NotifyPropertyChanged
。ObservableCollection
能够在集合本身更改(元素被添加或删除)时通知UI有关更改的信息。但是,ObservableCollection
不知道在您修改其中一个项目时发生的更改。要解决此问题,您可以订阅可观察集合的CollectionChange
事件,并在添加新项目时,订阅新项目的PropertyChanged。当引发PropertyChanged事件时,您可以触发列表上的通知OnPropertyChanged(()=>MyItems)代码>在实现此解决方案时应小心,并记住取消订阅事件,以避免内存泄漏
您可以在中看到我的意思的示例。ObservableCollection
能够在集合本身发生更改(元素被添加或删除)时通知UI更改。但是,ObservableCollection
不知道在您修改其中一个项目时发生的更改。要解决此问题,您可以订阅可观察集合的CollectionChange
事件,并在添加新项目时,订阅新项目的PropertyChanged。当引发PropertyChanged事件时,您可以触发列表上的通知OnPropertyChanged(()=>MyItems)代码>在实现此解决方案时应小心,并记住取消订阅事件,以避免内存泄漏
您可以在中看到我的意思的示例。您的MyDictionary
应该强制刷新。最简单的方法是重新分配其旧值,并在MyObject中实现INPC,如下所示:
public class MyObject: INotifyPropertyChanged
{
MyObservableDictionary _myDictionary;
public MyObservableDictionary MyDictionary {
get
{
return _myDictionary;
}
set
{
_myDictionary = value;
OnPropertyChanged("MyDictionary");
}
}
public MyObject()
{
MyDictionary = new MyObservableDictionary();
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string prop)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
更改值的示例代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
// vm is ViewModel instance, vm is DataContext set for Window
var old = vm.MyList[0].MyDictionary;
vm.MyList[0].MyDictionary[0].Value = "aaaa";
vm.MyList[0].MyDictionary = old;
}
我对此进行了测试,它将更改后的值显示为“aaaa”。您的MyDictionary
应该强制刷新。最简单的方法是重新分配其旧值,并在MyObject中实现INPC,如下所示:
public class MyObject: INotifyPropertyChanged
{
MyObservableDictionary _myDictionary;
public MyObservableDictionary MyDictionary {
get
{
return _myDictionary;
}
set
{
_myDictionary = value;
OnPropertyChanged("MyDictionary");
}
}
public MyObject()
{
MyDictionary = new MyObservableDictionary();
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string prop)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
更改值的示例代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
// vm is ViewModel instance, vm is DataContext set for Window
var old = vm.MyList[0].MyDictionary;
vm.MyList[0].MyDictionary[0].Value = "aaaa";
vm.MyList[0].MyDictionary = old;
}
我对此进行了测试,它将更改后的值显示为“aaaa”。与您的操作方式不同。该绑定
不会订阅INotifyCollectionChanged
,因为您要将集合绑定到字符串
属性。因此,当您更改集合时,没有人会听到它,绑定也不会更新目标。这不是您的操作方式。该绑定
不会订阅INotifyCollectionChanged
,因为您要将集合绑定到字符串
属性。因此,当您更改集合时,没有人会听到它,绑定也不会更新目标。@EdPlunkett我刚刚测试了建议的解决方案,它按照我的预期工作。我的意思是OnPropertyChanged(“MyItems”)并不像您提到的那样被忽略。如果需要,我可以提供代码来证明它。你为什么认为应该忽略它?我很确定我试过了,但没有成功。我以前就错了。只是测试了一下,你是对的,它就像你说的那样工作。谢谢你提醒我注意这一点。@EdPlunkett我刚刚测试了提议的解决方案,它按照我的预期工作。我的意思是OnPropertyChanged(“MyItems”)并不像您提到的那样被忽略。如果需要,我可以提供代码来证明它。你为什么认为应该忽略它?我很确定我试过了,但没有成功。我以前就错了。只是测试了一下,你是对的,它就像你说的那样工作。谢谢你提醒我注意这件事。