2010-11-22 77 views
2

我有幾列是數字並希望它們右對齊。這是一個有點做作的例子來展示我的問題:將默認資源樣式應用於所有DataGridTextColumns

<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是正確的,那麼我只需要明確地左對齊第一列。我怎麼能做到這一點,也許使用風格作爲資源?有沒有更好的辦法?

回答

7

DataGridTextColumn不會從FrameworkElement派生,因此您無法爲其創建樣式。

最簡單的方法就是爲DataGridCell創建一個樣式,並從那裏對齊TextBlock。然後設置CellStyle = {x:空}(或者你可能需要的任何其他方式)針對列不應該有這樣的

<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這樣的東西是必需的。

首先,我們需要一個可以「保持風格」的助手類。在它中,我們添加了所有我們希望能夠使用Style的屬性(這不在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> 

的作風和能夠在我們需要另一個助手類與TextColumnStyle屬性DataGridTextColumn應用此樣式。其中,我們使用反射和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這樣

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