c# - 如何将 WPF ItemsControl 源绑定到列表段
问题描述
我有一个ItemsControl
绑定到元素列表的。我怎样才能让它只显示该列表的一部分,例如,基于给定的Offset
and Count
?
显然我可以将一个IEnumerable
属性声明为MyList.Skip(Offset).Take(Count)
,在绑定中使用它并通知PropertyChanged
每次Offset
或被Count
修改。这很好用,除了每次ItemsControl
都会为其所有项目重新创建视图,即使对于那些不是新的项目也是如此。
我想一个更惯用的方法是有一个CollectionView
但它似乎不支持当前段的概念。我尝试使用基于索引的过滤器,但除了感觉不对之外,它还存在与以前相同的性能问题。
所以到目前为止我看到的唯一方法是ObservableCollection
使用正确的列表元素维护 an 并在绑定中使用它,但不应该有更简单的方法吗?
这是我的测试程序(我知道代码MyObservableCollection
在一般情况下不起作用)
MainWindow.xaml
<Window x:Class="ItemsControlSegmentView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ItemsControlSegmentView"
x:Name="This"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<Style TargetType="ItemsControl">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" Background="{Binding DataContext.CurrentColor, ElementName=This, Mode=OneTime}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding MyEnumerable}"/>
<ItemsControl ItemsSource="{Binding MyCollectionView}"/>
<ItemsControl ItemsSource="{Binding MyObservableCollection}"/>
</StackPanel>
<Slider Maximum="{Binding MyList.Count}" Value="{Binding Offset}"/>
<Slider Maximum="{Binding MaxCount}" Value="{Binding Count}"/>
</StackPanel>
</Window>
MainWindowViewModel
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Data;
using JetBrains.Annotations;
namespace ItemsControlSegmentView
{
public class MainWindowViewModel : INotifyPropertyChanged
{
private int offset;
private int count = 7;
private readonly Random random = new Random();
public string CurrentColor { get; private set; } = "White";
public int Offset
{
get { return offset; }
set
{
if (offset == value) return;
var atEnd = value > offset;
offset = value;
UpdateAllViews(atEnd);
OnPropertyChanged(nameof(MaxCount));
OnPropertyChanged();
}
}
public int Count
{
get { return count; }
set
{
if (count == value) return;
count = value;
UpdateAllViews(true);
OnPropertyChanged();
}
}
public int MaxCount => MyList.Count - Offset;
public List<string> MyList { get; } = new List<string>(Enum.GetNames(typeof(DayOfWeek)));
private void UpdateAllViews(bool atEnd)
{
CurrentColor = $"#{random.Next():X8}";
UpdateMyEnumerable();
UpdateMyCollectionView();
UpdateMyObservableCollection(atEnd);
}
public IEnumerable<string> MyEnumerable => MyList.Skip(Offset).Take(Count);
private void UpdateMyEnumerable() => OnPropertyChanged(nameof(MyEnumerable));
public ListCollectionView MyCollectionView { get; }
private void UpdateMyCollectionView() => MyCollectionView.Filter = entry =>
{
var indexOf = MyList.IndexOf((string)entry);
return indexOf >= Offset && indexOf < Offset + Count;
};
public ObservableCollection<string> MyObservableCollection { get; }
private void UpdateMyObservableCollection(bool atEnd)
{
foreach (var s in MyList.Except(MyEnumerable))
MyObservableCollection.Remove(s);
var i = 0;
foreach (var s in MyEnumerable.Except(MyObservableCollection))
if (atEnd) MyObservableCollection.Add(s);
else MyObservableCollection.Insert(i++, s);
}
public MainWindowViewModel()
{
MyCollectionView = new ListCollectionView(MyList);
MyObservableCollection = new ObservableCollection<string>(MyList);
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
这是将偏移滑块逐步滚动到右端和后退后窗口的外观。只有第三个ItemsControl
保留其现有条目:
解决方案
推荐阅读
- java - Java 在管道中生成自定义流
- php - 单击清除过滤器按钮时,将所有下拉列表设置为 php 中的默认值
- python - 返回 'Decimal' 值返回 Decimal('value') 而打印它不会
- java - 在 Maven 测试运行中执行时,使用 Spring 注释进行测试会导致 ClosedByInterruptException
- java - Spring boot - 配置第二个数据源以及 gloud gcp postgresql 主数据源
- java - 使用 Jena 查找所有子属性
- reactjs - 在反应中将数据从一个组件发送到另一个组件
- c# - C# PDFsharp:不透明绘制的 TIFF 图像
- hyperledger-fabric - Hyperledger Fabric 中的 Transaction ID 是如何生成的?
- angular - 如何修复未捕获的错误:模板解析错误:“nb-sidebar”不是已知元素: