wpf Listbox giving columns a header

2019-02-21 23:44发布

问题:

I have the following markup (xaml):

<ListBox Name="lbEurInsuredType" HorizontalContentAlignment="Stretch">
            <ListBox.ItemTemplate>
               <DataTemplate>
                    <Grid Margin="0,2">
                        <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100"></ColumnDefinition>
                            <ColumnDefinition Width="30"></ColumnDefinition><ColumnDefinition Width="2"></ColumnDefinition>
                            <ColumnDefinition Width="30"></ColumnDefinition>
                   </Grid.ColumnDefinitions>
                   <TextBlock Text="{Binding Title}"></TextBlock>
                   <TextBox Text="{Binding Uw}" Grid.Column="1"></TextBox>
                   <TextBox Text="{Binding Partner}" Grid.Column="3"></TextBox>
                </Grid>
            </DataTemplate></ListBox.ItemTemplate>

        </ListBox>

This all looks ok, but now above column 1 and 3 I want to place a header. Can anyone show me how I add headers to my two columns.

回答1:

Listview is surely the best option, but, if you need to use a listbox you could modify the template of the listbox in this way.

   <ListBox Name="lbEurInsuredType" HorizontalContentAlignment="Stretch">
        <ListBox.Template>
            <ControlTemplate>
                <DockPanel LastChildFill="True">
                    <Grid DockPanel.Dock="Top" Height="30">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="100"></ColumnDefinition>
                            <ColumnDefinition Width="30"></ColumnDefinition>
                            <ColumnDefinition Width="2"></ColumnDefinition>
                            <ColumnDefinition Width="30"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Label Grid.Column="0">Column 1</Label>
                        <Label Grid.Column="1">Column 2</Label>
                        <Label Grid.Column="2">Column 3</Label>
                        <Label Grid.Column="3">Column 4</Label>
                    </Grid>
                    <ItemsPresenter></ItemsPresenter>
                </DockPanel>
            </ControlTemplate>
        </ListBox.Template>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid Margin="0,2">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100"></ColumnDefinition>
                        <ColumnDefinition Width="30"></ColumnDefinition>
                        <ColumnDefinition Width="2"></ColumnDefinition>
                        <ColumnDefinition Width="30"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Title}"></TextBlock>
                    <TextBox Text="{Binding Uw}" Grid.Column="1"></TextBox>
                    <TextBox Text="{Binding Partner}" Grid.Column="3"></TextBox>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>


回答2:

I recommend that you use a ListView instead which more appropriate to you case, you could use a GridView inside and define the columns that you need then restyle them much more easily

 <ListView Name="lbEurInsuredType" HorizontalContentAlignment="Stretch" ItemsSource="{Binding Items}">
        <ListView.View>
            <GridView>
                <GridView.Columns>
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Title}"></TextBlock>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                        <GridViewColumn.Header>
                            <TextBlock Text="Column 1"></TextBlock>
                        </GridViewColumn.Header>
                    </GridViewColumn>
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Uw}"></TextBlock>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>                           
                    </GridViewColumn>
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Partner}"></TextBlock>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                        <GridViewColumn.Header>
                            <TextBlock Text="Column 3"></TextBlock>
                        </GridViewColumn.Header>
                    </GridViewColumn>
                </GridView.Columns>
            </GridView>
        </ListView.View>                      
    </ListView>


回答3:

I haven't run this so there might be some issue with the code but this will give you the idea to add headers to the ListBox

<ListBox Name="lbEurInsuredType" HorizontalContentAlignment="Stretch">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Margin="0,2">
                <Grid.RowDefinitions>
                    <RowDefinition  />
                    <RowDefinition  />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"></ColumnDefinition>
                    <ColumnDefinition Width="30"></ColumnDefinition>
                    <ColumnDefinition Width="2"></ColumnDefinition>
                    <ColumnDefinition Width="30"></ColumnDefinition>
                </Grid.ColumnDefinitions>

                <TextBlock Text="Title" ></TextBlock>
                <TextBlock Text="Uw" Grid.Column="1" ></TextBox>
                <TextBlock Text="Partner" Grid.Column="3" ></TextBox>

                <TextBlock Text="{Binding Title}" Grid.Row="1"></TextBlock>
                <TextBox Text="{Binding Uw}" Grid.Column="1" Grid.Row="1"></TextBox>
                <TextBox Text="{Binding Partner}" Grid.Column="3" Grid.Row="1"></TextBox>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>


回答4:

Even Listbox can be inside a user control with dynamic data template

    <Grid Style="{StaticResource TableHeader}">
        <Grid.Resources>
            <Style TargetType="{x:Type Border}" BasedOn="{StaticResource TableBorder}"/>
            <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource TextTableHeader}">
                <Setter Property="TextWrapping" Value="Wrap"/>
            </Style>
        </Grid.Resources>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Border BorderThickness="1">
            <TextBlock Text="Card"/>
        </Border>

        <Border Grid.Column="1" BorderThickness="0 1 1 1">
            <TextBlock Text="Type"/>
        </Border>

        <Border Grid.Column="2" BorderThickness="0 1 1 1">
            <TextBlock Text="Limit"/>
        </Border>

        <Border Grid.Column="3" BorderThickness="0 1 1 1">
            <TextBlock Text="Amount"/>
        </Border>

        <Border Grid.Column="4" BorderThickness="0 1 1 1">
            <TextBlock Text="Payment Due"/>
        </Border>

    </Grid>

    <ListBox Style="{StaticResource ListBoxStyle}"
             ItemsSource="{Binding Source}"
             SelectedItem="{Binding SelectedItem}"
             IsHitTestVisible="{Binding IsSelectionActive}"
             ItemTemplate="{Binding ItemTemplate}" />
</Grid>


回答5:

ListBox has no HeaderTemplate. ListView is not the best option because it does not support Width="*" . If you get desperate and go to DataGrid you might be getting a lot more than you need. The solution is to use a HeaderedItemsControl

Just change the name of the Collection you are binding to and change the binding properties.

<!-- actual XAML -->
       <HeaderedItemsControl 

                                                    ItemTemplate="{DynamicResource CorrugationItemTemplate}" 
                                                    ItemsSource="{Binding CorrugationItemCollection}"
                                                    Style="{DynamicResource CorrugationStyle}"/>


    <!-- this goes in the resource dict --> 

        <DataTemplate x:Key="CorrugationItemTemplate">
            <Grid Width="Auto" Background="#e1e1e1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="60"/>
                    <ColumnDefinition Width="60"/>
                    <ColumnDefinition Width="60"/>
                    <ColumnDefinition Width="60"/>
                </Grid.ColumnDefinitions>
                <Border Grid.Column="0"  Background="Lime" >
                    <Label Content="{Binding RangeLabel}" />
                </Border>
                <Border Grid.Column="1"   Background="Orange" >
                    <Label Content="{Binding LeftPreGrind}" />
                </Border>
                <Border Grid.Column="2"  Background="Lime" >
                    <Label Content="{Binding RightPreGrind}" />
                </Border>
                <Border Grid.Column="3"  Background="Orange" >
                    <Label Content="{Binding LeftPostGrind}" />
                </Border>
                <Border Grid.Column="4"  Background="Lime" >
                    <Label  Content="{Binding RightPostGrind}" />
                </Border>
            </Grid>
        </DataTemplate>

        <Style TargetType="{x:Type HeaderedItemsControl}" x:Key="CorrugationStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type HeaderedItemsControl}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="60"/>
                                <ColumnDefinition Width="60"/>
                                <ColumnDefinition Width="60"/>
                                <ColumnDefinition Width="60"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="20pt"/>
                                <RowDefinition Height="4*"/>
                            </Grid.RowDefinitions>

                            <Border Grid.Column="0"  Background="Orange" >
                                <Label Content="Range" />
                            </Border>
                            <Border Grid.Column="1"   Background="Lime" >
                                <Label Content="LeftPreGrind" />
                            </Border>
                            <Border Grid.Column="2"  Background="Orange" >
                                <Label Content="RightPreGrind" />
                            </Border>
                            <Border Grid.Column="3"  Background="Lime" >
                                <Label Content="LeftPostGrind" />
                            </Border>
                            <Border Grid.Column="4"  Background="Orange" >
                                <Label  Content="RightPostGrind" />
                            </Border>




                            <Grid Grid.Row="1" Grid.ColumnSpan="5" Width="Auto" Height="Auto" Background="White">
                                <ItemsPresenter/>
                            </Grid>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>


回答6:

You could nest a label (or a text block for that matter) inside one of the column definitions and style it accordingly.

<ColumnDefinition>
    <Label Content="Header 1" FontSize="20"/>
</ColumnDefinition>


标签: c# wpf listbox