c# - WPF/MVVM中ObservableCollection的双向绑定和过滤
问题描述
我在将应用程序重构为 MVVM 时正在学习 MVVM 模式。
我有一个模型类Machine
,它以ObservableCollection<Installation> Installations
.
在其中一个窗口(视图)中,我只需要显示那些具有更新的安装(因此满足以下条件):
private void InstallationsToUpdateFilter(object sender, FilterEventArgs e)
{
var x = (Installation)e.Item;
bool hasNewVersion = ShowAllEnabledInstallations ? true : x.NewVersion != null;
bool isSetAndOn = !String.IsNullOrEmpty(x.Path) && x.CheckForUpdatesFlag;
e.Accepted = isSetAndOn && hasNewVersion;
}
private void OnFilterChanged()
{
installationsToUpdateSource?.View?.Refresh();
}
我通过在我的 ViewModel 中过滤来做到这一点:
class NewVersionViewModel : ViewModelBase
{
private Machine machine = App.Machine;
...
public NewVersionViewModel(...)
{
...
InstallationsToUpdate.CollectionChanged += (s, e) =>
{
OnPropertyChanged("NewVersionsAvailableMessage");
OnFilterChanged();
};
installationsToUpdateSource = new CollectionViewSource();
installationsToUpdateSource.Source = InstallationsToUpdate;
installationsToUpdateSource.Filter += InstallationsToUpdateFilter;
}
public ObservableCollection<Installation> InstallationsToUpdate
{
get { return machine.Installations; }
set { machine.Installations = value; }
}
internal CollectionViewSource installationsToUpdateSource { get; set; }
public ICollectionView InstallationsToUpdateSourceCollection
{
get { return installationsToUpdateSource.View; }
}
...
}
这是由自定义 ListView 完成的:
<ListView ItemsSource="{Binding InstallationsToUpdateSourceCollection}" ... >
...
<ListView.ItemTemplate>
<DataTemplate>
<Grid ...>
<Grid ...>
<CheckBox Style="{StaticResource LargeCheckBox}"
IsChecked="{Binding Path=MarkedForUpdate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Path=HasNewVersion}"
/>
</Grid>
<Label Content="{Binding Path=InstalledVersion.Major}" Grid.Column="1" Grid.Row="0" FontSize="50" FontFamily="Segoe UI Black" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,-10,0,0"/>
...
<Grid.ContextMenu>
<ContextMenu>
...
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
所有这些都有效——直到我尝试“发送”<CheckBox IsChecked="{Binding Path=MarkedForUpdate...
回我的模型——所以它将被存储在那里。
怎么做?(我可以有某种二传手ICollectionView
吗?)
当前的架构可以改变。我最终需要什么:
- 显示
installations
模型中的项目( )ListView
(当前works
:) works
过滤/显示仅满足某些条件的安装(当前:)- 将复选框中的更改反映
MarkedForUpdate
回模型(当前not working
:)
我用谷歌搜索了很多,但找不到相关的解决方案或建议。任何帮助将不胜感激。谢谢!
解决方案
我发现了问题所在。尽管这是一个愚蠢的错误,但我仍然想分享它以节省某人的时间。
模型本身在上述配置中更新。问题是什么模型属性(Machine.Installations
在我的例子中)没有实现 INotifyPropertyChanged 接口,所以其他视图(通过它们相应的视图模型)不知道变化。因此,OnPropertyChanged/RaisePropertyChanged
不仅应该在ViewModel中使用,而且还应该在Model中使用。
希望这可以帮助某人。
推荐阅读
- android - 无论用户选择取消还是安装,如何从应用更新弹出窗口中获取回调
- javascript - 当我单击任何美国州地图时,fusionchart 中另一部分的图表过滤器
- regex - 正则表达式从请求 id 中提取文本
- html - 如何解决手机上的 iframe 高度问题
- python - 从 VBA 运行 Python 脚本不起作用
- python - `requests` 在 gcp cloud 上运行时返回不同结果的结果
- typescript - 如何在 TypeScript 4 中使用可变元组类型键入管道函数?
- machine-learning - 这个 CNN 框架构建有什么问题?
- autodesk-forge - 处理深度图像
- c# - C# 使用虚拟覆盖