ItemsControl的常见用法

ItemsControl基本概念

用法1:设置奇偶行不同

xml 复制代码
<ItemsControl AlternationCount="2" ItemsSource="{Binding Stars}">
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <DockPanel>
                <TextBlock DockPanel.Dock="Top" Text="Header" />
                <ItemsPresenter />
            </DockPanel>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border x:Name="border">
                <TextBlock Margin="10" Text="{Binding}" />
            </Border>
            <DataTemplate.Triggers>
                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                    <Setter TargetName="border" Property="Background" Value="#ccc" />
                </Trigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
csharp 复制代码
/// <summary>
/// 一些字符串,用来展示基础的 ItemsSource 绑定,奇偶行交替颜色,以及表头
/// </summary>
public ObservableCollection<string> Stars { get; } =
    new() { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune" };

用法2:展示几何

csharp 复制代码
/// <summary>
/// 用来展示替换 ItemsPanel 为 Canvas,以及修改 ItemContainerStyle
/// </summary>
public ObservableCollection<Shape> Shapes { get; } =
    new()
    {
    new(0, new(50, 50), Brushes.Red),
    new(1, new Point(150, 70), Brushes.Green),
    new(1, new Point(300, 160), Brushes.Blue),
    new(0, new Point(240, 260), Brushes.Yellow),
    };
xml 复制代码
<ItemsControl ItemsSource="{Binding Shapes}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <!--  主要使用ItemContainerStyle来控制Canvas等附加属性,因为元素会直接放在ContentPresenter上  -->
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Left" Value="{Binding Pos.X}" />
            <Setter Property="Canvas.Top" Value="{Binding Pos.Y}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle
                Name="rect"
                Width="40"
                Height="40"
                Fill="{Binding Color}" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Type}" Value="1">
                    <Setter TargetName="rect" Property="RadiusX" Value="20" />
                    <Setter TargetName="rect" Property="RadiusY" Value="20" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

用法3:不同数据类型展示

定义数据

csharp 复制代码
public abstract class Fruit
{
    public int Amount { get; set; }
    public string FruitType => this.GetType().Name;
}
public class Apple : Fruit { }
public class Banana : Fruit { }
/// <summary>
/// 用于展示在 Resources 中存放多个 DataType 不同的 DataTemplate 的效果
/// </summary>
public ObservableCollection<Fruit> Fruits { get; } =
    new()
    {
    new Apple { Amount = 3 },
    new Apple { Amount = 2 },
    new Banana { Amount = 6 },
    new Apple { Amount = 4 },
    new Banana { Amount = 1 },
    new Banana { Amount = 5 },
    };
xml 复制代码
<ItemsControl ItemsSource="{Binding Fruits}">
    
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:Apple}">
            <Border Height="30" Background="Aquamarine">
                <StackPanel VerticalAlignment="Center" Orientation="Horizontal">
                    <TextBlock Width="80" Text="{Binding FruitType}" />
                </StackPanel>
            </Border>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Banana}">
            <Border Height="30" Background="LightPink">
                <StackPanel VerticalAlignment="Center" Orientation="Horizontal">
                    <TextBlock Width="80" Text="{Binding FruitType}" />
                </StackPanel>
            </Border>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

用法4,相同类型不同属性使用不同模板

定义数据

csharp 复制代码
public record Employee(string Name, Gender Gender, int Age);

public enum Gender
{
    Male,
    Female
};
/// <summary>
/// 用于展示 DataTemplateSelector 的使用
/// </summary>
public ObservableCollection<Employee> Employees { get; } =
    new()
    {
    new("John", Gender.Male, 27),
    new("Anna", Gender.Female, 31),
    new("Joyce", Gender.Female, 28),
    new("Tony", Gender.Male, 40),
    new("Brian", Gender.Male, 36)
    };

要根据Gender性别属性显示不同的背景色,要使用ItemTemplateSelector。

ItemTemplateSelector

定义ItemTemplateSelector

csharp 复制代码
public class EmployeeTemplateSelector : DataTemplateSelector
{
    public DataTemplate MaleTemplate { get; set; }
    public DataTemplate FemaleTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var element = container as FrameworkElement;
        var employee = item as Employee;
        return employee!.Gender switch
        {
            Gender.Male => MaleTemplate,
            Gender.Female => FemaleTemplate,
            _ => throw new ArgumentException()
        };
    }
}

使用

xml 复制代码
<ItemsControl FontSize="18" ItemsSource="{Binding Employees}">
    <ItemsControl.ItemTemplateSelector>
        <local:EmployeeTemplateSelector>
            <local:EmployeeTemplateSelector.MaleTemplate>
                <DataTemplate>
                    <StackPanel Background="LightCyan" Orientation="Horizontal">
                        <TextBlock Width="80" Text="{Binding Name}" />
                        <TextBlock Width="80" Text="{Binding Gender}" />
                        <TextBlock Text="{Binding Age}" />
                    </StackPanel>
                </DataTemplate>
            </local:EmployeeTemplateSelector.MaleTemplate>
            <local:EmployeeTemplateSelector.FemaleTemplate>
                <DataTemplate>
                    <StackPanel Background="LightPink" Orientation="Horizontal">
                        <TextBlock Width="80" Text="{Binding Name}" />
                        <TextBlock Width="80" Text="{Binding Gender}" />
                    </StackPanel>
                </DataTemplate>
            </local:EmployeeTemplateSelector.FemaleTemplate>
        </local:EmployeeTemplateSelector>
    </ItemsControl.ItemTemplateSelector>
</ItemsControl>

ItemsControl和ListBox的区别

和ListBox不同的是,ItemsControl默认不启用UI虚拟化,在呈现数据量较大的时候会导致严重的性能问题。因此如果数据量较大,最好为其开启虚拟化,具体需要做的是:

1:(必需)将其ItemsPanel设置为虚拟化容器,如VirtualizingStackPanel。

2:(必需)重写ControlTemplate,为其添加ScrollViewer并将其的CanContentScroll属性设置为True。注意,用ScrollViewer包裹ItemsControl是无效的。

3:(非必需,进一步优化)在ItemsControl上设置附加属性VirtualizingPanel.VirtualizationMode为Recycling,以此进一步减少内存分配和回收压力

相关推荐
翔云 OCR API7 小时前
发票查验接口详细接收参数说明-C#语言集成完整示例-API高效财税管理方案
开发语言·c#
虫小宝9 小时前
高佣金的返利平台性能压测:从单接口到全链路的性能瓶颈分析
c#·linq
故事不长丨9 小时前
C#集合:解锁高效数据管理的秘密武器
开发语言·windows·c#·wpf·集合·winfrom·字典
jghhh0111 小时前
基于C#实现与三菱FX系列PLC串口通信
开发语言·算法·c#·信息与通信
故事不长丨11 小时前
C#队列深度剖析:解锁高效编程的FIFO密码
visualstudio·c#·wpf·多线程·winfrom·队列·queue
bugcome_com12 小时前
C# 反射(Reflection)超全解析
c#
bjzhang7514 小时前
Dorisoy.AMS--一款采用C# WinForm框架+SQLite数据库的企业/机构资产管理解决方案
sqlite·c#·资产管理
luming-0214 小时前
java报错解决:sun.net.utils不存
java·经验分享·bug·.net·intellij-idea
零度@15 小时前
Java消息中间件-Kafka全解(2026精简版)
java·kafka·c#·linq
leiming615 小时前
c++ QT 开发第二天,用ui按钮点亮实体led
开发语言·qt·ui