1

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.HorizontalAlignmentProperty, 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.

2 Answers 2

3

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);
Sign up to request clarification or add additional context in comments.

1 Comment

I could kiss you right now! :) It worked perfectly and now I just need to do some reading to make sure I fully understand it.
1

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.