2010-11-22 27 views
2

J'ai plusieurs colonnes qui sont numériques et veulent qu'elles soient justifiées à droite. Voici un exemple un peu artificiel démontrant ma question:Appliquer un style de ressource par défaut à tous les 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> 

Les styles de justification à droite sont répétées pour tous, mais la première colonne et semblent redondants. Si seulement je pouvais définir le DataGridTextColumns dans cette grille pour être justifié à droite, alors je n'aurais qu'à justifier explicitement la première colonne. Comment puis-je faire cela, peut-être en utilisant un style comme une ressource? Y a-t-il un meilleur moyen?

Répondre

7

DataGridTextColumn ne dérive pas de FrameworkElement de sorte que vous ne pouvez pas créer de style pour ce produit prêt à l'emploi. La meilleure façon de faire ce que vous cherchez est de créer un style pour DataGridCell et d'aligner à droite le TextBlock à partir de là. Réglez ensuite CellStyle = {x: Null} (ou tout autre style que vous voudrez peut-être) pour les colonnes qui ne devraient pas avoir cette

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

Mise à jour

Mais si vous ne voulez appliquer un style à un DataGridTextColumn quelque chose comme ceci est requis.

D'abord nous avons besoin d'une classe d'aide qui peut "tenir le style". Dans celui-ci, nous ajoutons toutes les propriétés que nous aimerions pouvoir Style (qui n'est pas dans FrameworkElement). Dans ce cas, 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); } 
    } 
} 

Ensuite, nous ajoutons le style en 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> 

Et pour être en mesure d'appliquer ce style sur un DataGridTextColumn nous avons besoin d'une autre classe d'assistance avec une propriété TextColumnStyle. Dans celui-ci, nous appliquons le style en utilisant la réflexion et 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); 
       } 
      } 
     } 
    } 
} 

Enfin, nous pouvons utiliser le style sur un DataGridTextColumn comme celui-ci

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