Search code examples
wpfxamldatagrid

How can I realize with my DataGrid that I have two headers?


My goal is it to let my DataGrid look like Picture2. So I created two DataGrids to realize this because i didnt find a better way to do this, but the solution is not very clean and I run into more and more problems. So in the first DataGrid I have the heading normal and in the second I have textBoxes in the heading that should act as a search bar. It looks like this with 2 DataGrid:

Example1

Because my goal is that my DataGrid will look like this in the end:

Picture2

The problem now is that when I click on the first header, my data cannot be sorted in ascending or descending order. This only works if I click the second header on the second datagrid. But the button for sorting in ascending or descending order should not be in the second header, but in the first header. The best thing would be to use a DataGrid for this, but I don't know how to implement it so that the headings are in the first header and when I click in the first header that everything is sorted in ascending or descending order. And with the second header directly below then the TextBoxes that should serve as a search bar and below then the values. How do I manage that when I want to cut everything into a DataGrid. First of all, here is my code:

<Grid>

    <DataGrid HorizontalAlignment="Left" Height="298.638" Margin="93.195,102.655,0,0" 
              VerticalAlignment="Top" Width="507.242">


        <DataGrid.Resources>
            <!--Design kopfzeile-->
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="Background" Value="Gray"/>
                <Setter Property="Foreground" Value="White"/>
                <Setter Property="BorderThickness" Value="0,0,1,0" />
                <Setter Property="BorderBrush" Value="White"/>
                <Setter Property="Padding" Value="5 0 0 0"/>
            </Style>

            <!--Deaktivieren Des rowheader-->
            <Style TargetType="{x:Type DataGridRowHeader}">
                <Setter Property="Background" Value="Transparent"/>
            </Style>

        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Width="*" Binding="{x:Null}" ClipboardContentBinding="{x:Null}" Header="Artikelnummer" FontSize="10" IsReadOnly="True"/>
            <DataGridTextColumn Width="*"  Binding="{x:Null}" ClipboardContentBinding="{x:Null}" FontSize="10" Header="Artikelnummer" IsReadOnly="True"/>
            <DataGridTextColumn Width="*"  Binding="{x:Null}" ClipboardContentBinding="{x:Null}" Header="Matchcode" IsReadOnly="True"/>
            <DataGridTextColumn Width="*"  Binding="{x:Null}" ClipboardContentBinding="{x:Null}" Header="Hersteller" IsReadOnly="True"/>
            <DataGridCheckBoxColumn Width="*"  Binding="{x:Null}" ClipboardContentBinding="{x:Null}" Header="CheckBox" />
        </DataGrid.Columns>
    </DataGrid>

    <!--!!!!!!Haupt DataGrid !!!!!-->
    <DataGrid AutoGenerateColumns="False" Height="282.293" HorizontalAlignment="Left" Margin="93.195,119,0,0" Name="gridd" VerticalAlignment="Top" Width="507.242" >
        <DataGrid.Columns >
            <DataGridTextColumn Width="*" Binding="{Binding Id}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Width="88.048">
                            <TextBox Name="IDSearcBox"  Width="88"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>
            
            <DataGridTextColumn Width="*" Binding="{Binding Name}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Width="88.048">
                            <TextBox Name="IDSearcBox"  Width="88"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <DataGridTextColumn Width="*" Binding="{Binding Birthday}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Width="88.048">
                            <TextBox Name="IDSearcBox"  Width="88"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <DataGridTextColumn Width="*" Binding="{Binding ort}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Width="88.048">
                            <TextBox Name="IDSearcBox"  Width="88"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <DataGridTextColumn Width="*" Binding="{Binding alter}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Width="88.048">
                            <TextBox Name="IDSearcBox"  Width="88"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

        </DataGrid.Columns>
    </DataGrid>


</Grid>

And in C#:

public MainWindow()
    {
        InitializeComponent();

        List<User> users = new List<User>();
        users.Add(new User() { Id = 1, Name = "John Doe", ort="Berlin", Birthday = new DateTime(1971, 7, 23), alter=18, } );
        users.Add(new User() { Id = 2, Name = "Jane Doe", ort = "Köln", Birthday = new DateTime(1974, 1, 17), alter = 28, });
        users.Add(new User() { Id = 3, Name = "Sammy Doe", ort = "Bayern", Birthday = new DateTime(1991, 9, 2), alter = 38, });

        gridd.ItemsSource = users;

    }

    public class User
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string ort { get; set; }

        public DateTime Birthday { get; set; }

        public int alter { get; set; }
    }

Solution

  • So I created two DataGrids to realize this because i didnt find a better way to do this, but the solution is not very clean and I run into more and more problems.

    Yes, trying to synchronize two DataGrids is certainly going to be problematic.

    What you should do is to add the TextBox to the header of the (single) DataGrid:

    <DataGrid ...>
        <DataGrid.Columns>
            <DataGridTextColumn SortMemberPath="Id" Binding="{Binding Id}">
                <DataGridTextColumn.Header>
                    <StackPanel>
                        <TextBlock Text="Id" />
                        <Separator />
                        <TextBox Name="IDSearcBox" Width="88"/>
                    </StackPanel>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>
            ...
        </DataGrid.Columns>
    </DataGrid>
    

    Then you will get the built-in sorting functionality "for free". Note the use of the SortMemberPath property.

    You can obviously add any element you want to header and style it to make it look as per your requirements.