2008-09-30 8 views
29
<my:DataGridTemplateColumn 
      CanUserResize="False" 
      Width="150" 
      Header="{Binding MeetingName, Source={StaticResource LocStrings}}" 
      SortMemberPath="MeetingName"> 
    </my:DataGridTemplateColumn> 

Tengo la columna anterior en un control de cuadrícula de Silverlight. Pero me está dando un error XamlParser debido a la forma en que estoy tratando de establecer la propiedad Header. ¿Alguien ha hecho esto antes? Quiero hacer esto para varios idiomas.Configuración dinámica del texto de encabezado de una columna DataGrid de Silverlight

También mi sintaxis para el enlace a un recurso es correcta porque lo probé en una etiqueta fuera de la cuadrícula.

Respuesta

28

No se puede vincular al encabezado porque no es un elemento de Framework. Puede hacer que el texto dinámico mediante la modificación de la plantilla de encabezado así:

xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" 
xmlns:dataprimitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data" 

<data:DataGridTemplateColumn> 
    <data:DataGridTemplateColumn.HeaderStyle> 
     <Style TargetType="dataprimitives:DataGridColumnHeader"> 
      <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate>           
        <TextBlock Text="{Binding MeetingName, Source={StaticResource LocStrings}}" />     
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
     </Style> 
    </data:DataGridTemplateColumn.HeaderStyle> 
</data:DataGridTemplateColumn> 
+0

Gran respuesta y gracias por el ejemplo de código – Kyle

+12

¿Cómo se conserva el estilo visual del encabezado original? –

+0

Gracias por la respuesta. Has ayudado mucho. –

1

¿Por qué no se establece simplemente en este código:

dg1.Columns[3].Header = SomeDynamicValue; 
0

que tiene alguna solución para la unión. Como usa DataGridTemlateColumn, subclasselo y agregue una propiedad de tipo Binding con el nombre, por ejemplo, "HeaderBinding". Ahora puede enlazar a esa propiedad desde el XAML. A continuación, debe propagar el enlace al TextBlock en el DataTemplate de su encabezado. Por ejemplo, puede hacerlo con el evento OnLoaded de ese TextBlock.

HeaderTextBlock.SetBinding(TextBlock.TextProperty, HeaderBinding); 

Eso es todo. Si tiene más columnas y desea usar solo una DataTemplate, entonces es un poco más complicado, pero la idea es la misma.

11

Para mantener el estilo visual de la cabecera original, utilice ContentTemplate en lugar de Plantilla:

<Setter Property="ContentTemplate"> 
<Setter.Value> 
    <DataTemplate> 
     <Image Source="<image url goes here>"/> 
    </DataTemplate> 
</Setter.Value> 

+0

Parece que no funciona el enlace en el DataTemplate en un TextBlock: reemplaza la imagen en su ejemplo. – ptoinson

+0

Esto no ayuda a mantener el estilo visual en mi experiencia. –

+5

Este método es definitivamente el camino a seguir, y SÍ mantiene el estilo visual. Si vuelve a crear la plantilla del encabezado completo, se convierte en un cuadro blanco que contiene lo que sea que coloque allí. Sin embargo, si utiliza ContentTemplate, se conserva el fondo existente del estilo de encabezado predeterminado. – RobSiklos

2

encontrado una solución interesante que también trabaja con el wpflocalizeaddin.codeplex.com:

Creado por Slyi

Utiliza un IValueConverter:

public class BindingConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value.GetType().Name == "Binding") 
     { 
      ContentControl cc = new ContentControl(); 
      cc.SetBinding(ContentControl.ContentProperty, value as Binding); 
      return cc; 
     } 
     else return value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 

     return null; 
    } 
} 

Y un estilo para el DataGridColumnHeader

<UserControl.Resources> 
    <local:BindingConverter x:Key="BindCon"/> 
    <Style x:Key="ColBinding" TargetType="dataprimitives:DataGridColumnHeader" > 
     <Setter Property="ContentTemplate" > 
      <Setter.Value> 
       <DataTemplate> 
        <ContentPresenter Content="{Binding Converter={StaticResource BindCon}}" /> 
       </DataTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</UserControl.Resources> 

para que pueda mantener su sintaxis de unión favorito en el atributo Header

<Grid x:Name="LayoutRoot" Background="White"> 
    <StackPanel> 
     <TextBox Text="binding header" x:Name="tbox" /> 

     <data:DataGrid ItemsSource="{Binding AllPeople,Source={StaticResource folks}}" AutoGenerateColumns="False" ColumnHeaderStyle="{StaticResource ColBinding}" > 
      <data:DataGrid.Columns> 
       <data:DataGridTextColumn Binding="{Binding ID}" 

             Header="{Binding Text, ElementName=tbox}" /> 
       <data:DataGridTextColumn Binding="{Binding Name}" 

             Header="hello" /> 
      </data:DataGrid.Columns> 
     </data:DataGrid> 
    </StackPanel> 

</Grid> 

http://cid-289eaf995528b9fd.skydrive.live.com/self.aspx/Public/HeaderBinding.zip

13

Mi solución fue utilizar una propiedad adjunta para establecer el enlace automáticamente:

public static class DataGridColumnHelper 
{ 
    public static readonly DependencyProperty HeaderBindingProperty = DependencyProperty.RegisterAttached(
     "HeaderBinding", 
     typeof(object), 
     typeof(DataGridColumnHelper), 
     new PropertyMetadata(null, DataGridColumnHelper.HeaderBinding_PropertyChanged)); 

    public static object GetHeaderBinding(DependencyObject source) 
    { 
     return (object)source.GetValue(DataGridColumnHelper.HeaderBindingProperty); 
    } 

    public static void SetHeaderBinding(DependencyObject target, object value) 
    { 
     target.SetValue(DataGridColumnHelper.HeaderBindingProperty, value); 
    } 

    private static void HeaderBinding_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     DataGridColumn column = d as DataGridColumn; 

     if (column == null) { return; } 

     column.Header = e.NewValue; 
    } 
} 

Luego, en el XAML:

<data:DataGridTextColumn util:DataGridColumnHelper.HeaderBinding="{Binding MeetingName, Source={StaticResource LocStrings}}" /> 
+0

Esto es exactamente lo que estaba buscando, gracias. – HolaJan

+1

A diferencia de la solución aceptada, esta solución puede hacer lo que hace la solución aceptada además de preservar el estilo original. Está funcionando para mí. +1 –

+0

Esto también funciona para mí. Esto es absolutamente PERFECTO, y lo que estoy buscando: estilo y código detrás, separados como conceptos, separados en XAML. Muchas gracias, esta debería ser la solución aceptada. – Sandrous

2

Parece mucho más simple para establecer el valor en el código, como se mencionó anteriormente:

dg1.Columns[3].Header = SomeDynamicValue; 

evita el uso de la sintaxis del organismo de la propiedad, que en mi caso parecía arruinar el diseño, aunque intenté usar ContentTemplate y Template.

Un punto en el que me colapsé fue que es mejor usar la notación dg1.Columns[3].Header en lugar de tratar de hacer referencia a una columna con nombre.

Había nombrado una de mis columnas e intenté hacer referencia a eso en el código, pero obtuve excepciones nulas. Usar el método Columns [index] funcionó bien, y pude asignarle al encabezado una cadena de texto basada en los recursos de localización.

1

Tenga en cuenta en la solución proporcionada por RobSiklos, Fuente {...} StaticResource es la clave, si va a pasar el RelativeSource como

Binding DataContext.SelectedHistoryTypeItem,RelativeSource={RelativeSource AncestorType=sdk:DataGrid}, 

puede que no funcione

Cuestiones relacionadas