【问题标题】:Displaying only available letters from an observable collection to a datagridview仅将可观察集合中的可用字母显示到 datagridview
【发布时间】:2021-11-17 08:36:11
【问题描述】:

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

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。

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

如果我执行以下操作:

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

然后我失去了通知以及能够将字母设置为真/假并反映它的能力。

在datagridview中我也有一个关于字母的组合框,以便用户可以更改它,所以我还需要管理它,以便使用的字母显示为红色,如果选中,用户将无法使用。

有没有办法解决这个问题?

【问题讨论】:

  • 对不起,我不会说你的语言
  • 对不起。我没有注意到我用英语以外的语言发帖。请明确:您使用的是 Forms.DadaGridView 还是 Controls.DataGrid (WPF)?如果是后者,您是如何将 DataGrid 绑定到您的 NetworkDrives 集合的?
  • 我正在使用 Stylet,所以 MVVM,{Binding NetworkDrives} 并且我标记了它的 WPF 问题

标签: c# wpf stylet


【解决方案1】:

如果您不想在视图模型中触摸源集合,可以在视图中使用过滤后的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;

【讨论】:

  • 这是个好主意,但是如果将项目添加到 NetworkDrives 或者我需要刷新它或其他什么,过滤器会更新吗?
  • 是的。如果 NetworkDrives 是一个可观察的集合并且其更改通知已正确实现,则将是。您最好的选择是将 NetworkDrives 设为只读。也就是说,该属性没有设置器。
  • 顺便说一句,在您的问题代码中,NetworkDrives 是一个字段,而不是一个属性。但是绑定不能与字段一起使用。使用以下代码更正它:public ObservableCollection&lt;NetworkDrive&gt; NetworkDrives {get;}= new();.
  • 是的,这是一个错字,感谢您的注意,有趣的是,我可以明确地将其设为只读,我会试一试,谢谢。
  • 效果很好,谢谢。您是否会说为此目的使用过滤是一种糟糕的设计,或者我本可以采取不同的方式?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-29
相关资源
最近更新 更多