c# - 我有一个 WPF Listview,我想根据复选框的值显示重复值或不显示重复值

标签 c# wpf linq listview

我想要的只是类似于 Linq Distinct 的东西,可用于显示或不显示重复项,具体取决于复选框的状态。

这是 XAML(删除了名称等所有属性,以及与布局相关的所有内容,以避免分散注意力):

<ScrollViewer>
    <ListView SelectionMode="Single"/>
</ScrollViewer>
<CheckBox Content="group duplicates" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"/>

我的 ListView 中的每个项目都是一个带有超链接的标签,因为它的内容会在点击时使用默认的互联网浏览器打开超链接的 NavigateUri 属性中设置的 Uri。

一些链接在应用程序运行时出现不止一次,这是相关的,因为它显示了这些 uri 的出现次数。我在构建列表时也无法去除重复项,因为它是按每个 uri 出现的时间排序的,这也是相关的。

因为人眼很难区分每个 uri,因为它们看起来很相似,所以能够做两件事会很实用:

  1. 在链接中注释 uri 在 ListView 中出现的次数,即使它显示重复项也是如此
  2. 将重复项合并为一个链接(正确注释出现的次数)

我希望达到的结果是这样的:

(显示重复项)

  • uri1 (2)
  • uri2 (3)
  • uri1 (2)
  • uri3 (1)
  • uri2 (3)
  • uri2 (3)

(分组重复)

  • uri1 (2)
  • uri2 (3)
  • uri3 (1)

这就是我目前在后面的代码中填充 listvew 的方式(不显示不相关的部分以避免分散注意力)

foreach (string uriStr in uriStrCollection)
{
    Uri uri = new Uri(uriStr);
    Label lbl = new Label();
    Hyperlink link = new Hyperlink();
    link.Inlines.Add(uriStr);
    link.NavigateUri = uri;
    link.RequestNavigate += link_RequestNavigate;
    lbl.Content = link;
    listView.Items.Add(lbl);
}

存储 uriStrCollection 不是一个好的解决方案,因为它很大并且基本上将相同的数据存储两次。

再次生成 uriStrCollection 是一个更糟糕的主意,因为该过程涉及更多的内存和计算。

我尝试在 ListView.Items 和 ListView.Items.SourceCollection 上使用 Linq 扩展方法,但我不能:Linq 方法甚至不显示自动完成,这对我来说很奇怪,特别是因为编译SourceCollection 的时间类型是 IEnumerable。

有什么想法吗?

最佳答案

既然您使用的是 WPF,那么让我们从 WPF 的方式开始——将数据与 UI 分开; UI 应该用于显示数据,而不是存储数据。

暂时忘记 UI。首先,创建您需要的类和数据结构来存储 URI 列表及其在代码中的出现,例如:

public class UriWithOccurrence
{
    public string UriString { get; set; }
    public int Occurrences { get; set; }
}

...

//Keep a global collection of URIs:
_allUris = new List<UriWithOccurrence>();

foreach (string uriStr in uriStrCollection)
{
    var item = new UriWithOccurrence()
               {
                   UriString = uriStr,
                   Occurrences = uriStrCollection.Count(s => (s == uriStr))
               };

    _allUris.Add(item);
}

现在我们开始考虑在 UI 中显示这些 URI,并创建一个可以列出 UriWithOccurrenceListView。请注意指向 UriWithOccurrence 中的属性的 DisplayMemberBinding:

<ListView x:Name="_list" >
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Link" DisplayMemberBinding="{Binding UriString}" />
            <GridViewColumn Header="#" DisplayMemberBinding="{Binding Occurrences}" />
        </GridView>
    </ListView.View>
</ListView>

为了连接点并查看一些 URI,我们将 ListView 的 ItemsSource 设置为我们的 URI 集合:

_list.ItemsSource = _allUris;

这篇文章更深入地解释了这一切:http://tech.pro/tutorial/742/wpf-tutorial-using-the-listview-part-1

要获得可点击的 URI,这个 MSDN 问题可能会有所帮助:WPF ListView "hyperlink url" column

最后,要使“Group duplicates”复选框起作用,一个快速但肮脏的解决方案可能是:

private void CheckBox_Checked(object sender, EventArgs e)
{
    _list.ItemsSource = _allUris;
}

private void CheckBox_UnChecked(object sender, EventArgs e)
{
    _list.ItemsSource = _allUris.GroupBy(u => u.UriString)
                                .Select(gr => gr.First());
}

最后的提示:

真正以 WPF 方式执行此操作,请阅读 MVVM 模式并将大部分代码放在 ViewModel 中。

关于c# - 我有一个 WPF Listview,我想根据复选框的值显示重复值或不显示重复值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22120283/

相关文章:

c# - 如何使用Caliburn Micro从DataGrid所选行设置ViewModel属性

C# 和 LINQ : ordering a query by a nested query's value

c# - 如何将文本文件读取到DataTable

c# - 在linq中有区别吗?

c# - LINQ 作为方法参数

wpf - 是否有等效于 System.Windows.Forms.Screen 的 WPF?

c# - ViewModel 的数据更改时,文本框不会更新

c# - 用于索引到 IEnumerableObjects 以实现高效多维数组排序的动态 LINQ 查询字符串

c# - EF6 在 linq 查询中使用自定义属性

c# - 如何获取.Net Core中进程的CPU使用率和虚拟内存?