【问题标题】:Apply a default resource style to all DataGridTextColumns将默认资源样式应用于所有 DataGridTextColumns
【发布时间】:2010-11-22 18:52:54
【问题描述】:

我有几列是数字的,希望它们是正确的。这是一个有点人为的例子来说明我的问题:

<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 设置为右对齐,那么我只需要显式地左对齐第一列。我该怎么做,也许使用样式作为资源?有没有更好的办法?

【问题讨论】:

    标签: c# wpf wpfdatagrid c#-4.0


    【解决方案1】:

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

    最简单的方法是为 DataGridCell 创建一个 Style 并从那里右对齐 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

    <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}">
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-31
      • 2010-11-24
      • 1970-01-01
      相关资源
      最近更新 更多