将默认资源样式应用于所有 DataGridTextColumn

发布于 2024-10-04 00:22:28 字数 2678 浏览 7 评论 0原文

我有几列数字,并希望它们右对齐。这是一个有点人为的示例,展示了我的问题:

<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Controls="clr-namespace:System.Windows.Controls;assembly=PresentationFramework" xmlns:Windows="clr-namespace:System.Windows;assembly=PresentationFramework" xmlns:Data="clr-namespace:System.Windows.Data;assembly=PresentationFramework" Title="MyApp"
        Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" Loaded="Window_Loaded">
  <Controls:DataGrid Name="MyDataGrid" IsReadOnly="True"
          xmlns="http://schemas.microsoft.com/wpf/2008/toolkit" ItemsSource="{Data:Binding}" AutoGenerateColumns="True">
    <Controls:DataGrid.Columns>
      <!-- This is a product name and is left justified by default -->
      <Controls:DataGridTextColumn Header="ProductName" Binding="{Data:Binding Path=ProductName}" />
      <!-- The rest of the columns are numeric and I would like for them to be right justified -->
      <Controls:DataGridTextColumn Header="ProductId1" Binding="{Data:Binding Path=ProductId1}" >
        <Controls:DataGridTextColumn.ElementStyle>
          <Windows:Style TargetType="Controls:TextBlock">
            <Windows:Setter Property="HorizontalAlignment" Value="Right"/>
          </Windows:Style>
        </Controls:DataGridTextColumn.ElementStyle>
      </Controls:DataGridTextColumn>
      <Controls:DataGridTextColumn Header="ProductId2" Binding="{Data:Binding Path=ProductId2}" >
        <Controls:DataGridTextColumn.ElementStyle>
          <Windows:Style TargetType="Controls:TextBlock">
            <Windows:Setter Property="HorizontalAlignment" Value="Right"/>
          </Windows:Style>
        </Controls:DataGridTextColumn.ElementStyle>
      </Controls:DataGridTextColumn>
      <Controls:DataGridTextColumn Header="ProductId3" Binding="{Data:Binding Path=ProductId3}" >
        <Controls:DataGridTextColumn.ElementStyle>
          <Windows:Style TargetType="Controls:TextBlock">
            <Windows:Setter Property="HorizontalAlignment" Value="Right"/>
          </Windows:Style>
        </Controls:DataGridTextColumn.ElementStyle>
      </Controls:DataGridTextColumn>
      <!-- More numeric columns follow... -->
    </Controls:DataGrid.Columns>
  </Controls:DataGrid>
</Window>

除了第一列之外的所有列都重复正确的对齐样式,并且似乎多余。如果我可以将此网格中的 DataGridTextColumns 设置为右对齐,那么我只需显式左对齐第一列。我该如何做到这一点,也许使用样式作为资源?有更好的办法吗?

I have several columns that are numeric and want them to be right justified. Here is a somewhat contrived example demonstrating my issue:

<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Controls="clr-namespace:System.Windows.Controls;assembly=PresentationFramework" xmlns:Windows="clr-namespace:System.Windows;assembly=PresentationFramework" xmlns:Data="clr-namespace:System.Windows.Data;assembly=PresentationFramework" Title="MyApp"
        Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" Loaded="Window_Loaded">
  <Controls:DataGrid Name="MyDataGrid" IsReadOnly="True"
          xmlns="http://schemas.microsoft.com/wpf/2008/toolkit" ItemsSource="{Data:Binding}" AutoGenerateColumns="True">
    <Controls:DataGrid.Columns>
      <!-- This is a product name and is left justified by default -->
      <Controls:DataGridTextColumn Header="ProductName" Binding="{Data:Binding Path=ProductName}" />
      <!-- The rest of the columns are numeric and I would like for them to be right justified -->
      <Controls:DataGridTextColumn Header="ProductId1" Binding="{Data:Binding Path=ProductId1}" >
        <Controls:DataGridTextColumn.ElementStyle>
          <Windows:Style TargetType="Controls:TextBlock">
            <Windows:Setter Property="HorizontalAlignment" Value="Right"/>
          </Windows:Style>
        </Controls:DataGridTextColumn.ElementStyle>
      </Controls:DataGridTextColumn>
      <Controls:DataGridTextColumn Header="ProductId2" Binding="{Data:Binding Path=ProductId2}" >
        <Controls:DataGridTextColumn.ElementStyle>
          <Windows:Style TargetType="Controls:TextBlock">
            <Windows:Setter Property="HorizontalAlignment" Value="Right"/>
          </Windows:Style>
        </Controls:DataGridTextColumn.ElementStyle>
      </Controls:DataGridTextColumn>
      <Controls:DataGridTextColumn Header="ProductId3" Binding="{Data:Binding Path=ProductId3}" >
        <Controls:DataGridTextColumn.ElementStyle>
          <Windows:Style TargetType="Controls:TextBlock">
            <Windows:Setter Property="HorizontalAlignment" Value="Right"/>
          </Windows:Style>
        </Controls:DataGridTextColumn.ElementStyle>
      </Controls:DataGridTextColumn>
      <!-- More numeric columns follow... -->
    </Controls:DataGrid.Columns>
  </Controls:DataGrid>
</Window>

The right justification styles are repeated for all but the first column and seem redundant. If only I could set the DataGridTextColumns in this grid to be right justified, then I would only have to explicitly left justify the first column. How can I do this, perhaps using a style as a resource? Is there a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

荆棘i 2024-10-11 00:22:28

DataGridTextColumn 不是从 FrameworkElement 派生的,因此您无法为其创建开箱即用的样式。

最简单的方法是为 DataGridCell 创建样式并从那里右对齐 TextBlock。 的列设置 CellStyle={x:Null} (或您可能想要的任何其他样式)

<Controls:DataGrid ...>
    <Controls:DataGrid.Resources>
        <Windows.Style TargetType="Controls:DataGridCell">
            <Windows.Setter Property="TextBlock.HorizontalAlignment" Value="Right"/>
        </Windows.Style>
    </Controls:DataGrid.Resources>
    <Controls:DataGrid.Columns>
        <!-- This is a product name and is left justified by default -->
        <Controls:DataGridTextColumn Header="ProductName"
                                     Binding="{Binding Path=ProductName}"
                                     CellStyle="{x:Null}"/>

然后为不应该有此更新

但是如果您确实想将样式应用于 DataGridTextColumn ,如下所示是必须的。

首先我们需要一个可以“保持风格”的辅助类。在其中,我们添加了我们希望能够设置样式的所有属性(不在 FrameworkElement 中)。在本例中为 ElementStyle。

public class DataGridTextColumnStyleHelper : FrameworkElement
{
    public DataGridTextColumnStyleHelper(){}
    public static readonly DependencyProperty ElementStyleProperty =
        DependencyProperty.Register(
            "ElementStyle",
            typeof(Style),
            typeof(DataGridTextColumnStyleHelper));
    public Style ElementStyle
    {
        get { return (Style)GetValue(ElementStyleProperty); }
        set { SetValue(ElementStyleProperty, value); }
    }
}

然后我们在 xaml 中添加样式

<Style x:Key="DataGridTextColumnStyle"
       TargetType="local:DataGridTextColumnStyleHelper">
    <Setter Property="ElementStyle">
        <Setter.Value>
            <Style TargetType="TextBlock">
                <Setter Property="HorizontalAlignment" Value="Right"/>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

并且为了能够在 DataGridTextColumn 上应用此样式,我们需要另一个具有 TextColumnStyle 属性的 Helper 类。在其中,我们使用反射和 SetValue 应用样式。

public class MyDataGridHelper : DependencyObject 
{
    private static readonly DependencyProperty TextColumnStyleProperty = DependencyProperty.RegisterAttached(
        "TextColumnStyle",
        typeof(Style),
        typeof(MyDataGridHelper),
        new PropertyMetadata(MyPropertyChangedCallback));
    public static void SetTextColumnStyle(DependencyObject element, string value)
    {
        element.SetValue(TextColumnStyleProperty, value);
    }
    public static Style GetTextColumnStyle(DependencyObject element)
    {
        return (Style)element.GetValue(TextColumnStyleProperty);
    }
    private static void MyPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (DesignerProperties.GetIsInDesignMode(d) == true)
        {
            return;
        }
        DataGridTextColumn textColumn = (DataGridTextColumn)d;
        Style textColumnStyle = e.NewValue as Style;
        foreach (SetterBase setterBase in textColumnStyle.Setters)
        {
            if (setterBase is Setter)
            {
                Setter setter = setterBase as Setter;
                if (setter.Value is BindingBase)
                {
                    //Not done yet..
                }
                else
                {
                    Type type = textColumn.GetType();
                    PropertyInfo propertyInfo = type.GetProperty(setter.Property.Name);
                    propertyInfo.SetValue(textColumn, setter.Value, null);
                }
            }
        }
    }
}

最后,我们可以像这样在 DataGridTextColumn 上使用 Style

<DataGridTextColumn Header="ProductId1"  Binding="{Binding Path=ProductId1}"
    local:MyDataGridHelper.TextColumnStyle="{StaticResource DataGridTextColumnStyle}">

DataGridTextColumn doesn't derive from FrameworkElement so you can't create a Style for it out-of-the-box.

The easiest way to do what you're after is to create a Style for DataGridCell and right align the TextBlock from there. Then set CellStyle={x:Null} (or any other style you might want) for the Columns that shouldn't have this

<Controls:DataGrid ...>
    <Controls:DataGrid.Resources>
        <Windows.Style TargetType="Controls:DataGridCell">
            <Windows.Setter Property="TextBlock.HorizontalAlignment" Value="Right"/>
        </Windows.Style>
    </Controls:DataGrid.Resources>
    <Controls:DataGrid.Columns>
        <!-- This is a product name and is left justified by default -->
        <Controls:DataGridTextColumn Header="ProductName"
                                     Binding="{Binding Path=ProductName}"
                                     CellStyle="{x:Null}"/>

Update

But if you do want to apply a Style to a DataGridTextColumn something like this is required.

First we need a helper class that can "hold the Style". In it, we add all the properties we would like to be able to Style (that isn't in FrameworkElement). In this case ElementStyle.

public class DataGridTextColumnStyleHelper : FrameworkElement
{
    public DataGridTextColumnStyleHelper(){}
    public static readonly DependencyProperty ElementStyleProperty =
        DependencyProperty.Register(
            "ElementStyle",
            typeof(Style),
            typeof(DataGridTextColumnStyleHelper));
    public Style ElementStyle
    {
        get { return (Style)GetValue(ElementStyleProperty); }
        set { SetValue(ElementStyleProperty, value); }
    }
}

Then we add the Style in xaml

<Style x:Key="DataGridTextColumnStyle"
       TargetType="local:DataGridTextColumnStyleHelper">
    <Setter Property="ElementStyle">
        <Setter.Value>
            <Style TargetType="TextBlock">
                <Setter Property="HorizontalAlignment" Value="Right"/>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

And to be able to apply this Style on a DataGridTextColumn we need another Helper class with a TextColumnStyle property. In it, we apply the style using reflection and SetValue.

public class MyDataGridHelper : DependencyObject 
{
    private static readonly DependencyProperty TextColumnStyleProperty = DependencyProperty.RegisterAttached(
        "TextColumnStyle",
        typeof(Style),
        typeof(MyDataGridHelper),
        new PropertyMetadata(MyPropertyChangedCallback));
    public static void SetTextColumnStyle(DependencyObject element, string value)
    {
        element.SetValue(TextColumnStyleProperty, value);
    }
    public static Style GetTextColumnStyle(DependencyObject element)
    {
        return (Style)element.GetValue(TextColumnStyleProperty);
    }
    private static void MyPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (DesignerProperties.GetIsInDesignMode(d) == true)
        {
            return;
        }
        DataGridTextColumn textColumn = (DataGridTextColumn)d;
        Style textColumnStyle = e.NewValue as Style;
        foreach (SetterBase setterBase in textColumnStyle.Setters)
        {
            if (setterBase is Setter)
            {
                Setter setter = setterBase as Setter;
                if (setter.Value is BindingBase)
                {
                    //Not done yet..
                }
                else
                {
                    Type type = textColumn.GetType();
                    PropertyInfo propertyInfo = type.GetProperty(setter.Property.Name);
                    propertyInfo.SetValue(textColumn, setter.Value, null);
                }
            }
        }
    }
}

Finally, we can use the Style on a DataGridTextColumn like this

<DataGridTextColumn Header="ProductId1"  Binding="{Binding Path=ProductId1}"
    local:MyDataGridHelper.TextColumnStyle="{StaticResource DataGridTextColumnStyle}">
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文