带有附加 属性 和自定义模板的 ListView GridViewColumnHeader
ListView GridViewColumnHeader with attached property and custom template
我正在尝试逐列自定义 ListView
的 GridViewColumnHeader
。我已经能够通过手动将每个列的 GridViewColumnHeader
设置为内联 XAML(请参阅“Thing 2”列)来做到这一点,这没问题但超级重复,但我真的宁愿带有一些附加属性的控件模板的可重用样式(尝试在“事物 1”列中)。
基本上,我需要设置度量单位文本块以及页脚标记文本块的样式。
附加属性似乎已设置,但我无法弄清楚如何在模板中提取它们的值。
我意识到 GridColumnHeader
不是可视化树的一部分,这可能是这里的主要问题,但它看起来很接近!
“事物 1”列的样式设置为内联 XAML,直到我弄清楚如何获取附加的 属性 值。理想情况下,它将在控件模板中设置为 ExampleListViewHeader
.
我已经删除了所有不相关的代码:
MainWindow.xaml
<Window.Resources>
<x:Array x:Key="ExampleItems" Type="{x:Type local:ExampleItems}">
<local:ExampleItems Cell1="Item 1-1" Cell2="Item 1-2" Cell3="Item 1-3" />
<local:ExampleItems Cell1="Item 2-1" Cell2="Item 2-2" Cell3="Item 2-3" />
<local:ExampleItems Cell1="Item 3-1" Cell2="Item 3-2" Cell3="Item 3-3" />
<local:ExampleItems Cell1="Item 4-1" Cell2="Item 4-2" Cell3="Item 4-3" />
</x:Array>
<Style x:Key="ExampleListView" TargetType="{x:Type ListView}">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="Margin" Value="0, 0, 0, 5" />
</Style>
<Style x:Key="ExampleListViewHeader" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<TextBlock Text="{TemplateBinding Content}" Width="{TemplateBinding Width}" Padding="2, 0" TextWrapping="Wrap" VerticalAlignment="Bottom"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="{DynamicResource PLC_Font}" />
<Setter Property="FontSize" Value="{DynamicResource PLC_FontSize_Sub_1}" />
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="Foreground" Value="Black" />
</Style>
</Window.Resources>
<Grid>
<ListView ItemsSource="{StaticResource ExampleItems}" Style="{StaticResource ExampleListView}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}">
<GridViewColumnHeader>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Thing 1" VerticalAlignment="Bottom"/>
<TextBlock Grid.Column="1" Text=" (ft) " FontSize="10" VerticalAlignment="Center"/>
<!--<TextBlock Grid.Column="2" Text="{TemplateBinding local:HeaderAttachedProperties.Marker}"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:HeaderAttachedProperties.Marker)}"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type GridViewColumn}}, Path=(local:HeaderAttachedProperties.Marker)}"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=GridViewColumn}, Path=(local:HeaderAttachedProperties.Marker)}"/>-->
</Grid>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn Width="100"
DisplayMemberBinding="{Binding Cell2}">
<GridViewColumnHeader>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Thing 2" VerticalAlignment="Bottom"/>
<TextBlock Grid.Column="1" Text=" (ft) " FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="*" FontSize="10" VerticalAlignment="Center"/>
</Grid>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn Header="Thing 3" DisplayMemberBinding="{Binding Cell3}" HeaderContainerStyle="{StaticResource ExampleListViewHeader}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Grid>
示例项目
public class ExampleItems
{
public string Cell1 { get; set; }
public string Cell2 { get; set; }
public string Cell3 { get; set; }
}
HeaderAttachedProperties
public class HeaderAttachedProperties : DependencyObject
{
public static readonly DependencyProperty MarkerProperty = DependencyProperty.RegisterAttached(
name: "Marker",
propertyType: typeof(string),
ownerType: typeof(HeaderAttachedProperties),
defaultMetadata: new PropertyMetadata(""));
public static string GetMarker(DependencyObject pDependencyObject)
{
return (string)pDependencyObject.GetValue(MarkerProperty);
}
public static void SetMarker(DependencyObject pDependencyObject, string pValue)
{
pDependencyObject.SetValue(MarkerProperty, pValue);
}
public static readonly DependencyProperty UofMProperty = DependencyProperty.RegisterAttached(
name: "UofM",
propertyType: typeof(string),
ownerType: typeof(HeaderAttachedProperties),
defaultMetadata: new PropertyMetadata(""));
public static string GetUofM(DependencyObject pDependencyObject)
{
return (string)pDependencyObject.GetValue(UofMProperty);
}
public static void SetUofM(DependencyObject pDependencyObject, string pValue)
{
pDependencyObject.SetValue(UofMProperty, pValue);
}
}
您不一定需要 ControlTemplate
。您可以改用 DataTemplate
。为了在 GridViewColumn
上绑定附加属性,您可以使用 GridViewColumnHeader
.
的 Column
属性
<Style x:Key="ListViewHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="FontFamily" Value="{DynamicResource PLC_Font}" />
<Setter Property="FontSize" Value="{DynamicResource PLC_FontSize_Sub_1}" />
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="Foreground" Value="Black" />
</Style>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}"
HeaderContainerStyle="{StaticResource ListViewHeaderStyle}">
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Thing 1" VerticalAlignment="Bottom"/>
<TextBlock Grid.Column="1" Text="{Binding Column.(local:HeaderAttachedProperties.UofM), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Column.(local:HeaderAttachedProperties.Marker), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}"/>
</Grid>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
</GridViewColumn>
如果您也对第一个 TextBlock
进行参数化,则可以提取并重复使用它。
<DataTemplate x:Key="ListViewHeaderTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Column.(local:HeaderAttachedProperties.Anything), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Column.(local:HeaderAttachedProperties.UofM), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Column.(local:HeaderAttachedProperties.Marker), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}"/>
</Grid>
</DataTemplate>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}"
HeaderTemplate="{StaticResource ListViewHeaderTemplate}"
HeaderContainerStyle="{StaticResource ListViewHeaderStyle}">
</GridViewColumn>
您当然可以改为更改 ControlTemplate
,但您应该小心,因为它定义了控件的视觉外观和状态。在您当前的模板中,您失去了大部分状态。
<Style x:Key="ListViewHeader" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Column.(local:HeaderAttachedProperties.Anything), RelativeSource={RelativeSource TemplatedParent}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Column.(local:HeaderAttachedProperties.UofM), RelativeSource={RelativeSource TemplatedParent}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Column.(local:HeaderAttachedProperties.Marker), RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="{DynamicResource PLC_Font}" />
<Setter Property="FontSize" Value="{DynamicResource PLC_FontSize_Sub_1}" />
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="Foreground" Value="Black" />
</Style>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}">
<GridViewColumnHeader Style="{StaticResource ListViewHeader}"/>
</GridViewColumn>
我省略了 TextWrapping
和 VerticalAlignment
属性,在需要的地方重新引入它们。
我正在尝试逐列自定义 ListView
的 GridViewColumnHeader
。我已经能够通过手动将每个列的 GridViewColumnHeader
设置为内联 XAML(请参阅“Thing 2”列)来做到这一点,这没问题但超级重复,但我真的宁愿带有一些附加属性的控件模板的可重用样式(尝试在“事物 1”列中)。
基本上,我需要设置度量单位文本块以及页脚标记文本块的样式。
附加属性似乎已设置,但我无法弄清楚如何在模板中提取它们的值。
我意识到 GridColumnHeader
不是可视化树的一部分,这可能是这里的主要问题,但它看起来很接近!
“事物 1”列的样式设置为内联 XAML,直到我弄清楚如何获取附加的 属性 值。理想情况下,它将在控件模板中设置为 ExampleListViewHeader
.
我已经删除了所有不相关的代码:
MainWindow.xaml
<Window.Resources>
<x:Array x:Key="ExampleItems" Type="{x:Type local:ExampleItems}">
<local:ExampleItems Cell1="Item 1-1" Cell2="Item 1-2" Cell3="Item 1-3" />
<local:ExampleItems Cell1="Item 2-1" Cell2="Item 2-2" Cell3="Item 2-3" />
<local:ExampleItems Cell1="Item 3-1" Cell2="Item 3-2" Cell3="Item 3-3" />
<local:ExampleItems Cell1="Item 4-1" Cell2="Item 4-2" Cell3="Item 4-3" />
</x:Array>
<Style x:Key="ExampleListView" TargetType="{x:Type ListView}">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="Margin" Value="0, 0, 0, 5" />
</Style>
<Style x:Key="ExampleListViewHeader" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<TextBlock Text="{TemplateBinding Content}" Width="{TemplateBinding Width}" Padding="2, 0" TextWrapping="Wrap" VerticalAlignment="Bottom"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="{DynamicResource PLC_Font}" />
<Setter Property="FontSize" Value="{DynamicResource PLC_FontSize_Sub_1}" />
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="Foreground" Value="Black" />
</Style>
</Window.Resources>
<Grid>
<ListView ItemsSource="{StaticResource ExampleItems}" Style="{StaticResource ExampleListView}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}">
<GridViewColumnHeader>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Thing 1" VerticalAlignment="Bottom"/>
<TextBlock Grid.Column="1" Text=" (ft) " FontSize="10" VerticalAlignment="Center"/>
<!--<TextBlock Grid.Column="2" Text="{TemplateBinding local:HeaderAttachedProperties.Marker}"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:HeaderAttachedProperties.Marker)}"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type GridViewColumn}}, Path=(local:HeaderAttachedProperties.Marker)}"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=GridViewColumn}, Path=(local:HeaderAttachedProperties.Marker)}"/>-->
</Grid>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn Width="100"
DisplayMemberBinding="{Binding Cell2}">
<GridViewColumnHeader>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Thing 2" VerticalAlignment="Bottom"/>
<TextBlock Grid.Column="1" Text=" (ft) " FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="*" FontSize="10" VerticalAlignment="Center"/>
</Grid>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn Header="Thing 3" DisplayMemberBinding="{Binding Cell3}" HeaderContainerStyle="{StaticResource ExampleListViewHeader}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Grid>
示例项目
public class ExampleItems
{
public string Cell1 { get; set; }
public string Cell2 { get; set; }
public string Cell3 { get; set; }
}
HeaderAttachedProperties
public class HeaderAttachedProperties : DependencyObject
{
public static readonly DependencyProperty MarkerProperty = DependencyProperty.RegisterAttached(
name: "Marker",
propertyType: typeof(string),
ownerType: typeof(HeaderAttachedProperties),
defaultMetadata: new PropertyMetadata(""));
public static string GetMarker(DependencyObject pDependencyObject)
{
return (string)pDependencyObject.GetValue(MarkerProperty);
}
public static void SetMarker(DependencyObject pDependencyObject, string pValue)
{
pDependencyObject.SetValue(MarkerProperty, pValue);
}
public static readonly DependencyProperty UofMProperty = DependencyProperty.RegisterAttached(
name: "UofM",
propertyType: typeof(string),
ownerType: typeof(HeaderAttachedProperties),
defaultMetadata: new PropertyMetadata(""));
public static string GetUofM(DependencyObject pDependencyObject)
{
return (string)pDependencyObject.GetValue(UofMProperty);
}
public static void SetUofM(DependencyObject pDependencyObject, string pValue)
{
pDependencyObject.SetValue(UofMProperty, pValue);
}
}
您不一定需要 ControlTemplate
。您可以改用 DataTemplate
。为了在 GridViewColumn
上绑定附加属性,您可以使用 GridViewColumnHeader
.
Column
属性
<Style x:Key="ListViewHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="FontFamily" Value="{DynamicResource PLC_Font}" />
<Setter Property="FontSize" Value="{DynamicResource PLC_FontSize_Sub_1}" />
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="Foreground" Value="Black" />
</Style>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}"
HeaderContainerStyle="{StaticResource ListViewHeaderStyle}">
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Thing 1" VerticalAlignment="Bottom"/>
<TextBlock Grid.Column="1" Text="{Binding Column.(local:HeaderAttachedProperties.UofM), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Column.(local:HeaderAttachedProperties.Marker), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}"/>
</Grid>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
</GridViewColumn>
如果您也对第一个 TextBlock
进行参数化,则可以提取并重复使用它。
<DataTemplate x:Key="ListViewHeaderTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Column.(local:HeaderAttachedProperties.Anything), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Column.(local:HeaderAttachedProperties.UofM), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Column.(local:HeaderAttachedProperties.Marker), RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}}"/>
</Grid>
</DataTemplate>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}"
HeaderTemplate="{StaticResource ListViewHeaderTemplate}"
HeaderContainerStyle="{StaticResource ListViewHeaderStyle}">
</GridViewColumn>
您当然可以改为更改 ControlTemplate
,但您应该小心,因为它定义了控件的视觉外观和状态。在您当前的模板中,您失去了大部分状态。
<Style x:Key="ListViewHeader" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Column.(local:HeaderAttachedProperties.Anything), RelativeSource={RelativeSource TemplatedParent}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Column.(local:HeaderAttachedProperties.UofM), RelativeSource={RelativeSource TemplatedParent}}" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Column.(local:HeaderAttachedProperties.Marker), RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="{DynamicResource PLC_Font}" />
<Setter Property="FontSize" Value="{DynamicResource PLC_FontSize_Sub_1}" />
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="Foreground" Value="Black" />
</Style>
<GridViewColumn Width="100"
local:HeaderAttachedProperties.Marker="1"
local:HeaderAttachedProperties.UofM=" (ft) "
DisplayMemberBinding="{Binding Cell1}">
<GridViewColumnHeader Style="{StaticResource ListViewHeader}"/>
</GridViewColumn>
我省略了 TextWrapping
和 VerticalAlignment
属性,在需要的地方重新引入它们。