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"/>
                        ...
                        <Grid.ContextMenu>
                            <ContextMenu>
                                ...
                            </ContextMenu>
                        </Grid.ContextMenu>
                    </Grid>                        
                </DataTemplate>
            </ListView.ItemTemplate>                
        </ListView>

所有这些工作-直到我尝试“发送” <CheckBox IsChecked="{Binding Path=MarkedForUpdate...回到我的模型之前-它将存储在该模型中。

如何完成? (我可以在ICollectionView上使用二传手吗?)

可以更改当前架构。我最终需要的是:

  1. installations显示模型中的项目(ListView)(当前:works
  2. 过滤/仅显示符合某些条件的安装(当前为works
  3. MarkedForUpdate复选框中的更改反映回模型(当前为not working

我在Google上搜索了很多,但是找不到相关的解决方案或建议。 任何帮助将不胜感激。谢谢!

解决方法

我发现了问题所在。尽管这是一个愚蠢的错误,但我还是想分享它以节省别人的时间。

模型本身按照上述配置进行更新。问题在于哪个模型属性(在我的情况下为Machine.Installations)没有实现INotifyPropertyChanged接口,因此其他视图(通过其相应的ViewModel)不知道更改。因此,不仅应该在{strong> ViewModel 中使用OnPropertyChanged/RaisePropertyChanged,而且还应在 Model 中使用 // Enable TLS 1.1 and 1.2 System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)768 | (System.Net.SecurityProtocolType)3072; // OR -- Enable JUST TLS 1.2 //System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072;

希望这可能对某人有所帮助。