样式触发器的WPF属性目标

时间:2014-10-08 15:00:42

标签: c# .net wpf xaml wpfdatagrid

我正在使用DataGrid上添加的“Tag”属性定义自定义DataGridTextColumn,如下所示

<local:DataGridTextColumn Binding="{Binding Path=Company}" 
                          Header="Company" 
                          Tag="String" 
                          IsReadOnly="True" />

我已经定义了一些资源XAML来控制网格的渲染,但是我遇到了问题。我想在DataGridColumnHeader上呈现自定义ContextMenu,具体取决于使用触发器的“Tag”属性的值。但是,我找不到从样式中引用列“Tag”值的方法。我已经尝试过DataTriggers和常规触发器。

<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=local:DataGridTextColumn}, Path=Tag}" Value="String">
            <Setter Property="ContextMenu" Value="{StaticResource ColumnHeaderContextMenuString}" />
        </DataTrigger>
        <Trigger Property="Tag" Value="Int">
            <Setter Property="ContextMenu" Value="{StaticResource ColumnHeaderContextMenuInt}" />
        </Trigger>
        <Trigger Property="Tag" Value="DateTime">
            <Setter Property="ContextMenu" Value="{StaticResource ColumnHeaderContextMenuDateTime}" />
        </Trigger>
    </Style.Triggers>

5 个答案:

答案 0 :(得分:0)

首先,您必须从样式化的DataGridColumnHeader元素到基础列。从那里,您可以深入了解Tag。试试这个:

<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.Tag}" 
             Value="String">
    <Setter Property="ContextMenu"
            Value="{StaticResource ColumnHeaderContextMenuString}" />
</DataTrigger>

但是如果您要使用标题样式,为什么不简单地为每个基础数据类型设置样式,并相应地设置每个列的HeaderStyle?如果每个标题样式仅适用于单个数据类型,则不需要触发器。

答案 1 :(得分:0)

不要在设计时强制执行样式决策,方法是更改​​Tag属性,以便在运行时应用样式。为什么呢?

如果您可以在设计时更改标记,则可以使列标题符合特定样式。

目前还不清楚为什么需要 Rube Goldberg 设置设计时间风格的方式。

答案 2 :(得分:0)

DataGridColumnHeader基类型中没有标记属性。 使用:<Style TargetType="{x:Type local:DataGridTextColumn}">和简单的触发器

答案 3 :(得分:0)

嘛!在你的工作中一切都很顺利,但解决问题需要一些概念:

关键概念:(可选阅读材料)'DataGridTextColumn'的标题属性处理其中的两种类型的数据,一种是Type:string,另一种是'Type:DataGridColumnHeader'。与许多其他Framework Properties相比,字符串类型值在编译时不会转换为其他类型。因此设置值Header =“Company”仍保留在sting数据类型中,并且设置ContextMenu属性意义较小。

有很多解决方案/方法可以解决这个问题,但我发布了接近你的方法的答案......

解决方案:正在设置样式,但设置标题属性如下:

 <DataGridTextColumn x:Name="CompanyColumn" Width="*" Binding="{Binding Company}">
     <DataGridTextColumn.Header>
         <DataGridColumnHeader Content="Company" Tag="String"/>
     </DataGridTextColumn.Header>
 </DataGridTextColumn>

为了支持其他访问者,我发送完整的代码来理解这种方法。

<Window x:Class="AnswerNo1.SolutionA" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    Title="SolutionA" Height="250" Width="400">
<Window.Resources>
    <ContextMenu x:Key="ColumnHeaderContextMenuString">
        <MenuItem Header="_Sentence case."/>
        <MenuItem Header="_lowercase"/>
        <MenuItem Header="_UPPERCASE"/>
        <MenuItem Header="_Capitalize Each Word"/>
        <MenuItem Header="_tOGGLE cASE"/>
    </ContextMenu>
    <ContextMenu x:Key="ColumnHeaderContextMenuInt">
        <MenuItem Header="Show _SUM"/>
        <MenuItem Header="Show _Mean"/>
        <MenuItem Header="Show Standard Deviation"/>
        <MenuItem Header="Subtract All Form ..."/>
        <MenuItem Header="Toggle Sign"/>
    </ContextMenu>
    <ContextMenu x:Key="ColumnHeaderContextMenuDateTime">
        <MenuItem Header="Show Time Graph"/>
        <MenuItem Header="Show Minimum Data"/>
        <MenuItem Header="Show Maximum Data"/>
        <MenuItem Header="Show Mode Day"/>
        <MenuItem Header="Sort by day name"/>
    </ContextMenu>
    <Style TargetType="{x:Type DataGridColumnHeader}">
        <Style.Triggers>
            <Trigger Property="Tag" Value="String">
                <Setter Property="ContextMenu" Value="{StaticResource ColumnHeaderContextMenuString}" />
            </Trigger>
            <Trigger Property="Tag" Value="Int">
                <Setter Property="ContextMenu" Value="{StaticResource ColumnHeaderContextMenuInt}" />
            </Trigger>
            <Trigger Property="Tag" Value="DateTime">
                <Setter Property="ContextMenu" Value="{StaticResource ColumnHeaderContextMenuDateTime}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <DataGrid x:Name="YourDataGrid" AutoGenerateColumns="False" Margin="3">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="CompanyColumn" Width="*" Binding="{Binding Company}">
                <DataGridTextColumn.Header>
                    <DataGridColumnHeader Content="Company" Tag="String"/>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>
            <DataGridTextColumn x:Name="ReputationColumn" Width="*" Binding="{Binding Reputation}">
                <DataGridTextColumn.Header>
                    <DataGridColumnHeader Content="Reputation" Tag="Int"/>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>
            <DataGridTextColumn x:Name="SetupDateColumn" Width="*" Binding="{Binding SetupDate}">
                <DataGridTextColumn.Header>
                    <DataGridColumnHeader Content="Setup Date" Tag="DateTime"/>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Label Content="Tag for 1st Column: "/>
        <ComboBox Grid.Column="1" SelectedItem="{Binding Header.Tag, ElementName=CompanyColumn}" >
            <System:String>String</System:String>
            <System:String>Int</System:String>
            <System:String>DateTime</System:String>
        </ComboBox>
    </Grid>
</Grid>

答案 4 :(得分:0)

我最终不得不为此编写非XAML解决方案。这是获得具有内容感知上下文菜单的可重用DataGrid的唯一方法。每次添加网格时,其他解决方案都需要大量的配置(加上我无法让它们工作)。