Como definir o DataContext em um cabeçalho de coluna DataGrid
-
21-09-2019 - |
Pergunta
No meu Silverlight 3 Controle do usuário Estou mostrando um básico Grade de dados ao controle. Preciso gerar as colunas programaticamente do seguinte modo:
Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
dataGrid.Columns.Add(col);
O estilo é definido da seguinte maneira:
<Style x:Name="ColumnStyle" x:Key="ColumnHeaderStyle"
TargetType="prim:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Loaded="StackPanel_Loaded">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Data}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Eu quero Defina o contexto de dados do cabeçalho para um objeto "cabeçalho" (com propriedades "nome" e "dados" que são referenciadas no datatemplate). Infelizmente, não posso usar o evento Stackpanel_loaded, conforme sugerido em outro lugar, porque o manipulador de eventos também é chamado quando o usuário inicia uma operação de arrastar e soltar em coluna.
Qual é a maneira correta de definir o datacontext de um cabeçalho de coluna Datagrid?
Solução
Acontece que se pode usar o Propriedade do cabeçalho (que é do objeto de tipo) como o DataContext para o Datatemplate (definido como mostrado acima):
Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
col.Header = myHeaderDataContext; // DataContext for ColumnHeaderStyle
dataGrid.Columns.Add(col);
Outras dicas
Veja como você faria isso em xaml (isso funciona no WPF; não tenho certeza se funciona no SL)
<DataGridTextColumn Binding="{Binding Path=Discount}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Content" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.DiscountHeader}" />
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
Com base na resposta de Matt, criei a solução de ligar o cabeçalho no DataGridCellsPanel
que em Snoop parecia ter o contexto de dados correto:
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource CenterAlignedColumnHeaderStyle}">
<Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
E isso não é intrusivo na maneira como você ainda pode herdar de cabeçalhos de estilo personalizado (veja exemplos acima) ou evento o estilo de cabeçalho da coluna base:
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
Esta solução tem a vantagem de ser XAML pura e limpa e se referir ao ancestral mais próximo que segura o datacontext correto, em vez de tentar alcançar o DataContext dos elementos de hierarquia superior, como o UserControl.