正确实现自定义网格列表视图控件
Properly implement a custom grid listview control
我有一个以类似方式使用三个网格列表视图的应用程序:
(实际上,"standard label"是一个过滤框控件,但为了这个问题,我选择了最简单的视觉元素。)
我想我可以 "refactor" 使用 ControlTemplate
将三个列表视图合并到同一个 "styled" 自定义列表视图中:
<Window x:Class="customlistview.StyledWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:customlistview"
mc:Ignorable="d"
Title="StyledWindow" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="StyledListView" TargetType="{x:Type ListView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListView}">
<Border x:Name="_Border" Background="#ADADAD">
<Grid x:Name="_Grid" SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition Height="46*"/>
<RowDefinition Height="auto" MaxHeight="25"/>
</Grid.RowDefinitions>
<ScrollViewer>
<ItemsPresenter x:Name="ContentsItems" Grid.Row="0"></ItemsPresenter>
</ScrollViewer>
<Label Grid.Row="1" Background="#FF5C8F88">Standard Label</Label>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="MainGrid" Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView x:Name="ModulesList" Style="{StaticResource StyledListView}" ItemsSource="{Binding ModulesItems}" Grid.Row="0">
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="Module" Width="300" DisplayMemberBinding="{Binding ModuleName, TargetNullValue='N/A'}"/>
</GridView>
</ListView.View>
</ListView>
<ListView x:Name="ItemsAList" Style="{StaticResource StyledListView}" Grid.Row="1">
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="ItemsA" Width="300" DisplayMemberBinding="{Binding ItemA, TargetNullValue='N/A'}"/>
</GridView>
</ListView.View>
</ListView>
<ListView x:Name="ItemsBList" Style="{StaticResource StyledListView}" Grid.Row="2">
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="ItemsB" Width="300" DisplayMemberBinding="{Binding ItemB, TargetNullValue='N/A'}"/>
<GridViewColumn Header="SpecificToB" Width="300" DisplayMemberBinding="{Binding SpecificToB, TargetNullValue='N/A'}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
有效,但是我丢失了 GridView 列 Headers(并且背景颜色也发生了变化):
向列表视图添加页脚的正确方法是什么?
这里是相关代码:
StyledWindow.xaml.cs
using System.Collections.Generic;
using System.Windows;
namespace customlistview
{
public class ModuleItem
{
public ModuleItem(string Name)
{
ModuleName = Name;
}
public string ModuleName { get; set; }
}
public class ItemAItem
{
public ItemAItem(string Name)
{
ItemA = Name;
}
public string ItemA { get; set; }
}
public class ItemBItem
{
public ItemBItem(string Name, string Specific)
{
ItemB = Name;
SpecificToB = Specific;
}
public string ItemB { get; set; }
public string SpecificToB { get; set; }
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class StyledWindow : Window
{
public List<ModuleItem> ModulesItems;
public List<ItemAItem> ItemsAItems;
public List<ItemBItem> ItemsBItems;
public StyledWindow()
{
InitializeComponent();
this.ModulesItems = new List<ModuleItem>();
this.ItemsAItems = new List<ItemAItem>();
this.ItemsBItems = new List<ItemBItem>();
this.ModulesItems.Add(new ModuleItem("Mod1"));
this.ModulesItems.Add(new ModuleItem("Mod2"));
this.ModulesItems.Add(new ModuleItem("Mod3"));
ModulesList.ItemsSource = ModulesItems;
this.ItemsAItems.Add(new ItemAItem("ItemA1"));
this.ItemsAItems.Add(new ItemAItem("ItemA2"));
this.ItemsAItems.Add(new ItemAItem("ItemA3"));
ItemsAList.ItemsSource = ItemsAItems;
this.ItemsBItems.Add(new ItemBItem("ItemB1", "SpecificItemB1"));
this.ItemsBItems.Add(new ItemBItem("ItemB2", "SpecificItemB2"));
this.ItemsBItems.Add(new ItemBItem("ItemB3", "SpecificItemB3"));
ItemsBList.ItemsSource = ItemsBItems;
}
}
}
恕我直言,您将 "footer" 添加到 ListView
的方式并没有错。您的问题是未显示列的 headers。罪魁祸首是您在 ControlTemplate
.
中使用的 ScrollViewer
在标准 ListView
的模板中,ScrollViewer
正是执行 技巧 的控件。确实到了ListView
's ScrollViewer
a peculiar style is applied (a style with a definite template which shows columns'headers).
所以解决方案是将相同的样式应用到您的 ScrollViewer
。我们很幸运,因为该样式使用了定义明确的键,即常量值 GridView.GridViewScrollViewerStyleKey
。所以你的模板将是:
<Border x:Name="_Border" Background="#ADADAD">
<Grid x:Name="_Grid" SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto" MaxHeight="25"/>
</Grid.RowDefinitions>
<ScrollViewer Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}">
<ItemsPresenter x:Name="ContentsItems" Grid.Row="0" />
</ScrollViewer>
<Label Grid.Row="1" Background="#FF5C8F88">Standard Label</Label>
</Grid>
</Border>
希望对您有所帮助
我有一个以类似方式使用三个网格列表视图的应用程序:
(实际上,"standard label"是一个过滤框控件,但为了这个问题,我选择了最简单的视觉元素。)
我想我可以 "refactor" 使用 ControlTemplate
将三个列表视图合并到同一个 "styled" 自定义列表视图中:
<Window x:Class="customlistview.StyledWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:customlistview"
mc:Ignorable="d"
Title="StyledWindow" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="StyledListView" TargetType="{x:Type ListView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListView}">
<Border x:Name="_Border" Background="#ADADAD">
<Grid x:Name="_Grid" SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition Height="46*"/>
<RowDefinition Height="auto" MaxHeight="25"/>
</Grid.RowDefinitions>
<ScrollViewer>
<ItemsPresenter x:Name="ContentsItems" Grid.Row="0"></ItemsPresenter>
</ScrollViewer>
<Label Grid.Row="1" Background="#FF5C8F88">Standard Label</Label>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="MainGrid" Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView x:Name="ModulesList" Style="{StaticResource StyledListView}" ItemsSource="{Binding ModulesItems}" Grid.Row="0">
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="Module" Width="300" DisplayMemberBinding="{Binding ModuleName, TargetNullValue='N/A'}"/>
</GridView>
</ListView.View>
</ListView>
<ListView x:Name="ItemsAList" Style="{StaticResource StyledListView}" Grid.Row="1">
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="ItemsA" Width="300" DisplayMemberBinding="{Binding ItemA, TargetNullValue='N/A'}"/>
</GridView>
</ListView.View>
</ListView>
<ListView x:Name="ItemsBList" Style="{StaticResource StyledListView}" Grid.Row="2">
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="ItemsB" Width="300" DisplayMemberBinding="{Binding ItemB, TargetNullValue='N/A'}"/>
<GridViewColumn Header="SpecificToB" Width="300" DisplayMemberBinding="{Binding SpecificToB, TargetNullValue='N/A'}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
有效,但是我丢失了 GridView 列 Headers(并且背景颜色也发生了变化):
向列表视图添加页脚的正确方法是什么?
这里是相关代码:
StyledWindow.xaml.cs
using System.Collections.Generic;
using System.Windows;
namespace customlistview
{
public class ModuleItem
{
public ModuleItem(string Name)
{
ModuleName = Name;
}
public string ModuleName { get; set; }
}
public class ItemAItem
{
public ItemAItem(string Name)
{
ItemA = Name;
}
public string ItemA { get; set; }
}
public class ItemBItem
{
public ItemBItem(string Name, string Specific)
{
ItemB = Name;
SpecificToB = Specific;
}
public string ItemB { get; set; }
public string SpecificToB { get; set; }
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class StyledWindow : Window
{
public List<ModuleItem> ModulesItems;
public List<ItemAItem> ItemsAItems;
public List<ItemBItem> ItemsBItems;
public StyledWindow()
{
InitializeComponent();
this.ModulesItems = new List<ModuleItem>();
this.ItemsAItems = new List<ItemAItem>();
this.ItemsBItems = new List<ItemBItem>();
this.ModulesItems.Add(new ModuleItem("Mod1"));
this.ModulesItems.Add(new ModuleItem("Mod2"));
this.ModulesItems.Add(new ModuleItem("Mod3"));
ModulesList.ItemsSource = ModulesItems;
this.ItemsAItems.Add(new ItemAItem("ItemA1"));
this.ItemsAItems.Add(new ItemAItem("ItemA2"));
this.ItemsAItems.Add(new ItemAItem("ItemA3"));
ItemsAList.ItemsSource = ItemsAItems;
this.ItemsBItems.Add(new ItemBItem("ItemB1", "SpecificItemB1"));
this.ItemsBItems.Add(new ItemBItem("ItemB2", "SpecificItemB2"));
this.ItemsBItems.Add(new ItemBItem("ItemB3", "SpecificItemB3"));
ItemsBList.ItemsSource = ItemsBItems;
}
}
}
恕我直言,您将 "footer" 添加到 ListView
的方式并没有错。您的问题是未显示列的 headers。罪魁祸首是您在 ControlTemplate
.
ScrollViewer
在标准 ListView
的模板中,ScrollViewer
正是执行 技巧 的控件。确实到了ListView
's ScrollViewer
a peculiar style is applied (a style with a definite template which shows columns'headers).
所以解决方案是将相同的样式应用到您的 ScrollViewer
。我们很幸运,因为该样式使用了定义明确的键,即常量值 GridView.GridViewScrollViewerStyleKey
。所以你的模板将是:
<Border x:Name="_Border" Background="#ADADAD">
<Grid x:Name="_Grid" SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto" MaxHeight="25"/>
</Grid.RowDefinitions>
<ScrollViewer Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}">
<ItemsPresenter x:Name="ContentsItems" Grid.Row="0" />
</ScrollViewer>
<Label Grid.Row="1" Background="#FF5C8F88">Standard Label</Label>
</Grid>
</Border>
希望对您有所帮助