仅将可观察集合中的可用字母显示到数据网格视图

Displaying only available letters from an observable collection to a datagridview

也许这是一个糟糕的设计理念,但这是我的想法:

public class NetworkDrive : BaseNotify
{
    private char letter;
    public char Letter
    {
        get => letter;
        set => SetAndNotify(ref letter, value, nameof(Letter));
    }

    private string name;
    public string Name
    {
        get => name;
        set => SetAndNotify(ref name, value, nameof(Letter));
    }

    private bool isLetterAvailable;
    public bool IsLetterAvailable
    {
        get => isLetterAvailable;
        set => SetAndNotify(ref isLetterAvailable, value, nameof(Letter));
    }
}

public class EditDriveViewModel : Screen
{
    public ObservableCollection<NetworkDrive> NetworkDrives { get; } = new();

}

NetworkDrives 中填满了所有字母,当用户选择一个字母并为其命名时,该字母不再可用,因此 IsLetterAvailable 设置为 false。

我想在数据网格视图中列出它,但只列出正在使用的字母,即:IsLetterAvailable 设置为 false 的字母,但如果我将 ItemsSource 用于 NetworkDrives,它将列出所有内容。

如果我执行以下操作:

public ObservableCollection<NetworkDrive> UsedNetworkDrives
{
    get => NetworkDrives.Where(x => !x.IsLetterAvailable).ToList();
}

然后我失去了通知和能够将字母设置为 true/false 并反映它的能力。

在datagridview中我还有一个关于字母的组合框,这样用户就可以改变它,所以我还需要管理它,以便用过的字母显示为红色,如果选择了用户就不能使用。

有办法解决吗?

如果您不想在视图模型中触及源集合,您可以在视图中使用过滤 CollectionViewSource

<Window.Resources>
    <CollectionViewSource x:Key="cvs" Source="{Binding NetworkDrives}"
                              Filter="CollectionViewSource_Filter"
                              IsLiveFilteringRequested="True"
                              xmlns:s="clr-namespace:System;assembly=mscorlib">
        <CollectionViewSource.LiveFilteringProperties>
            <s:String>IsLetterAvailable</s:String>
        </CollectionViewSource.LiveFilteringProperties>
    </CollectionViewSource>
</Window.Resources>
...
<ComboBox x:Name="cmb"
          ItemsSource="{Binding Source={StaticResource cvs}}"
          DisplayMemberPath="Name" />

    private void CollectionViewSource_Filter(object sender, FilterEventArgs e) =>
        e.Accepted = e.Item is NetworkDrive networkDrive
          && networkDrive.IsLetterAvailable;