C# ListBox ObservableCollection属性未更新
在获取包含ObservableCollection的列表框时遇到一些问题,该列表框将在项目的属性发生更改时更新。项所在的对象类型正在使用INotifyPropertyChanged和PropertyChanged()。(对我来说)有趣的是列表框不能按我想要/需要的方式工作,但我可以用另一种方式让它工作。我的MVVM基于以下文章/代码: 我正试图模拟他的工作区,以包含BuildRepository中的服务器配置。但是,我不想让“AllServerConfigs”成为该工作区中的一个选项卡,而是希望它成为左侧的一个列表框,用户可以在其中打开已关闭选项卡的配置。列表框正在更新以添加/删除,但属性没有更新(例如,如果保存新名称) 这是C# ListBox ObservableCollection属性未更新,c#,wpf,mvvm,listbox,observablecollection,C#,Wpf,Mvvm,Listbox,Observablecollection,在获取包含ObservableCollection的列表框时遇到一些问题,该列表框将在项目的属性发生更改时更新。项所在的对象类型正在使用INotifyPropertyChanged和PropertyChanged()。(对我来说)有趣的是列表框不能按我想要/需要的方式工作,但我可以用另一种方式让它工作。我的MVVM基于以下文章/代码: 我正试图模拟他的工作区,以包含BuildRepository中的服务器配置。但是,我不想让“AllServerConfigs”成为该工作区中的一个选项卡,而是希望
主窗口.XAML
;datacontext设置为“RepositoryViewModel”
这里是ServerConfigViewModel
public class ServerConfigViewModel : WorkspaceViewModel, IDataErrorInfo
{
readonly ServerConfig _serverConfig;
readonly BuildRepository _buildRepository;
#region Server Config Fields
public string Name
{
get
{
return _serverConfig.Name;
}
set
{
if (value == _serverConfig.Name)
{
return;
}
_serverConfig.Name = value;
base.OnPropertyChanged("Name");
}
}
#region Presentation Properties
public override string DisplayName
{
get
{
if (_serverConfig.Name == null)
{
return "New Server";
}
return _serverConfig.Name;
}
}
#region Constructors
public ServerConfigViewModel(ServerConfig serverConfig, BuildRepository buildRepository)
{
if (serverConfig == null)
{
throw new ArgumentNullException("serverConfig");
}
if (buildRepository == null)
{
throw new ArgumentNullException("buildRepository");
}
_serverConfig = serverConfig;
_buildRepository = buildRepository;
}
#endregion
#region Public Methods
public void Save()
{
if (!_serverConfig.IsValid)
{
throw new InvalidOperationException("Server Config is not valid, cannot be saved");
}
if (this.IsNewServerConfig)
{
_buildRepository.AddServerConfig(_serverConfig);
}
base.OnPropertyChanged("DisplayName");
}
#endregion
}
public class AllConfigsViewModel : WorkspaceViewModel
{
#region Properties
readonly BuildRepository _buildRepository;
#endregion
#region Constructor
public AllConfigsViewModel(BuildRepository buildRepository)
{
base.DisplayName = "All Configs";
_buildRepository = buildRepository;
_buildRepository.ServerConfigAdded += this.OnServerConfigAddedToRepository;
this.CreateAllServerConfigs();
}
void CreateAllServerConfigs()
{
List<ServerConfigViewModel> all =
(from config in _buildRepository.GetServerConfigs()
select new ServerConfigViewModel(config, _buildRepository)).ToList();
foreach (ServerConfigViewModel scvm in all)
scvm.PropertyChanged += this.OnServerConfigViewModelPropertyChanged;
this.AllServerConfigs = new ObservableCollection<ServerConfigViewModel>(all);
this.AllServerConfigs.CollectionChanged += this.OnCollectionChanged;
}
#endregion
#region Public Interface
public ObservableCollection<ServerConfigViewModel> AllServerConfigs
{
get;
private set;
}
#endregion
#region Event Handling
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count != 0)
foreach (ServerConfigViewModel configVm in e.NewItems)
configVm.PropertyChanged += this.OnServerConfigViewModelPropertyChanged;
if (e.OldItems != null && e.OldItems.Count != 0)
foreach (ServerConfigViewModel configVm in e.OldItems)
configVm.PropertyChanged -= this.OnServerConfigViewModelPropertyChanged;
}
void OnServerConfigViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
string DisplayName = "DisplayName";
(sender as ServerConfigViewModel).VerifyPropertyName(DisplayName);
if (e.PropertyName == DisplayName)
{
this.OnPropertyChanged("AllServerConfigs");
}
}
void OnServerConfigAddedToRepository(object sender, ServerConfigAddedEventArgs e)
{
var viewModel = new ServerConfigViewModel(e.NewServerConfig, _buildRepository);
this.AllServerConfigs.Add(viewModel);
//this.OnPropertyChanged("AllServerConfigs");
}
#endregion
}
这里是AllConfigsViewModel
public class ServerConfigViewModel : WorkspaceViewModel, IDataErrorInfo
{
readonly ServerConfig _serverConfig;
readonly BuildRepository _buildRepository;
#region Server Config Fields
public string Name
{
get
{
return _serverConfig.Name;
}
set
{
if (value == _serverConfig.Name)
{
return;
}
_serverConfig.Name = value;
base.OnPropertyChanged("Name");
}
}
#region Presentation Properties
public override string DisplayName
{
get
{
if (_serverConfig.Name == null)
{
return "New Server";
}
return _serverConfig.Name;
}
}
#region Constructors
public ServerConfigViewModel(ServerConfig serverConfig, BuildRepository buildRepository)
{
if (serverConfig == null)
{
throw new ArgumentNullException("serverConfig");
}
if (buildRepository == null)
{
throw new ArgumentNullException("buildRepository");
}
_serverConfig = serverConfig;
_buildRepository = buildRepository;
}
#endregion
#region Public Methods
public void Save()
{
if (!_serverConfig.IsValid)
{
throw new InvalidOperationException("Server Config is not valid, cannot be saved");
}
if (this.IsNewServerConfig)
{
_buildRepository.AddServerConfig(_serverConfig);
}
base.OnPropertyChanged("DisplayName");
}
#endregion
}
public class AllConfigsViewModel : WorkspaceViewModel
{
#region Properties
readonly BuildRepository _buildRepository;
#endregion
#region Constructor
public AllConfigsViewModel(BuildRepository buildRepository)
{
base.DisplayName = "All Configs";
_buildRepository = buildRepository;
_buildRepository.ServerConfigAdded += this.OnServerConfigAddedToRepository;
this.CreateAllServerConfigs();
}
void CreateAllServerConfigs()
{
List<ServerConfigViewModel> all =
(from config in _buildRepository.GetServerConfigs()
select new ServerConfigViewModel(config, _buildRepository)).ToList();
foreach (ServerConfigViewModel scvm in all)
scvm.PropertyChanged += this.OnServerConfigViewModelPropertyChanged;
this.AllServerConfigs = new ObservableCollection<ServerConfigViewModel>(all);
this.AllServerConfigs.CollectionChanged += this.OnCollectionChanged;
}
#endregion
#region Public Interface
public ObservableCollection<ServerConfigViewModel> AllServerConfigs
{
get;
private set;
}
#endregion
#region Event Handling
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count != 0)
foreach (ServerConfigViewModel configVm in e.NewItems)
configVm.PropertyChanged += this.OnServerConfigViewModelPropertyChanged;
if (e.OldItems != null && e.OldItems.Count != 0)
foreach (ServerConfigViewModel configVm in e.OldItems)
configVm.PropertyChanged -= this.OnServerConfigViewModelPropertyChanged;
}
void OnServerConfigViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
string DisplayName = "DisplayName";
(sender as ServerConfigViewModel).VerifyPropertyName(DisplayName);
if (e.PropertyName == DisplayName)
{
this.OnPropertyChanged("AllServerConfigs");
}
}
void OnServerConfigAddedToRepository(object sender, ServerConfigAddedEventArgs e)
{
var viewModel = new ServerConfigViewModel(e.NewServerConfig, _buildRepository);
this.AllServerConfigs.Add(viewModel);
//this.OnPropertyChanged("AllServerConfigs");
}
#endregion
}
由于ListBox的DisplayMemberPath绑定到DisplayName,请添加
base.OnPropertyChanged("DisplayName");
到ServerConfigViewModel中的Name属性的setter之后
base.OnPropertyChanged("Name");
这应该告诉它在绑定DisplayName的任何位置刷新视图。我会说创建一个新项目,用更少的代码尝试它,如果有任何问题,返回StackOverflow并提出问题。很难查看您的代码并诊断问题。嗨,Dilshod,我已经更新了我的原始帖子,删除了所有与ObservableCollections和ListBox无关的代码。这是一个全新的项目,是尽我所能的小(以我在WPF的技能)。我只从我需要的MVVM示例中提取代码,并将其转换为我自己的对象类型。我只是不明白为什么在一个可观察集合中显示的项目不更新,而在另一个集合中显示的项目看起来完全相同。太棒了!你能发布MainWindow.xaml.csI的代码吗?我已经用
MainWindow.xaml.cs
更新了底部的帖子,它是一个空代码。我还发布了App.cs
的代码。只是尝试了一下,没有改变。base.OnPropertyChanged(“DisplayName”)
按钮也会调用Save
按钮,这是我真正想要更新它的时候。
base.OnPropertyChanged("Name");