Using code behind only add button to dynamically generated WPF DataGrid column's header
I have a wpf datagrid that has it's columns generated dynamically in code and I need to insert small buttons in each column's header to the right of the text to implement custom (complex) filtering in a popup dialog.
I'm having trouble figuring out how to insert a button into a datagrid column header using only code behind.
This is the route I started going down (commented out bit) but it doesn't work:
private static DataGridTextColumn GetTextColumn(string ColumnName, string FormatString, bool AlignRight)
{
DataGridTextColumn c = new DataGridTextColumn();
c.Header = Test.Common.UIBizObjectCache.LocalizedText.GetLocalizedText(ColumnName);
c.Binding = new System.Windows.Data.Binding(ColumnName);
if (!string.IsNullOrWhiteSpace(FormatString))
c.Binding.StringFormat = FormatString;
if (AlignRight)
{
Style cellRightAlignedStyle = new Style(typeof(DataGridCell));
cellRightAlignedStyle.Setters.Add(new Setter(DataGridCell.Horizo开发者_开发百科ntalAlignmentProperty, HorizontalAlignment.Right));
c.CellStyle = cellRightAlignedStyle;
}
//var buttonTemplate = new FrameworkElementFactory(typeof(Button));
//buttonTemplate.Text = "X";
//buttonTemplate.AddHandler(
// Button.ClickEvent,
// new RoutedEventHandler((o, e) => HandleColumnHeaderButtonClick(o, e))
// );
//c.HeaderTemplate=new DataTemplate(){VisualTree = buttonTemplate};
return c;
}
I get an invalidoperationexception "'ContentPresenter' type must implement IAddChild to be used in FrameworkElementFactory AppendChild."
Clearly I'm doing it wrong. :) Any help would be greatly appreciated.
Do you need to use a template? If not use the normal Header
property:
string colProperty = "Name";
DataGridTextColumn col = new DataGridTextColumn();
col.Binding = new Binding(colProperty);
var spHeader = new StackPanel() { Orientation = Orientation.Horizontal };
spHeader.Children.Add(new TextBlock(new Run(colProperty)));
var button = new Button();
button.Click += Button_Filter_Click;
button.Content = "Filter";
spHeader.Children.Add(button);
col.Header = spHeader;
dataGrid.Columns.Add(col);
For create a column header with an image button, you can do this in xaml :
<Window.Resources>
<BitmapImage x:Key="Img" UriSource="/Img/yourImage.png"/>
</Window.Resources>
<Datagrid Name="yourDatagrid">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="Btn" Click="Btn_Click" >
<DockPanel>
<Image Source="{StaticResource ResourceKey=Img}" Height="16" Width="16"/>
</DockPanel>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</Datagrid>
Or you can autogenerate this in code behind like this :
Xaml :
<Window.Resources>
<BitmapImage x:Key="Img" UriSource="/Img/yourImage.png"/>
</Window.Resources>
C# :
Datagrid yourDatagrid = new Datagrid();
DataGridTemplateColumn colBtn = new DataGridTemplateColumn();
DataTemplate DttBtn = new DataTemplate();
FrameworkElementFactory btn = new FrameworkElementFactory(typeof(Button));
FrameworkElementFactory panel = new FrameworkElementFactory(typeof(DockPanel));
FrameworkElementFactory img = new FrameworkElementFactory(typeof(Image));
img.SetValue(Image.SourceProperty, (BitmapImage)FindResource("Img"));
img.SetValue(Image.HeightProperty, Convert.ToDouble(16));
img.SetValue(Image.WidthProperty, Convert.ToDouble(16));
panel.AppendChild(img);
btn.AppendChild(panel);
btn.AddHandler(Button.ClickEvent, new RoutedEventHandler(Btn_Click));
DttBtn.VisualTree = btn;
colBtn.CellTemplate = DttBtn;
yourDatagrid.Columns.Add(colBtn);
精彩评论