【问题标题】:C# WPF - ListBox with DataTemplate - add extra "header" rowC# WPF - 带有 DataTemplate 的 ListBox - 添加额外的“标题”行
【发布时间】:2018-06-14 21:43:37
【问题描述】:

我有带有 DataTemplate 的 ListBox,如下所示:

 <ListBox ItemsSource="{Binding}" BorderBrush="Transparent" 
         Grid.IsSharedSizeScope="True"
         HorizontalContentAlignment="Stretch"
         Grid.Row="1"
         Grid.Column="0" Grid.ColumnSpan="4"         
         Name="playerList">          
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="2">
                        <Grid Margin="4">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="3*" />
                                <ColumnDefinition Width="3*" />
                                <ColumnDefinition Width="3*" />
                                <ColumnDefinition Width="3*" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="16"  />
                            <TextBlock Grid.Column="1" Text="{Binding Drinked }" FontWeight="Bold" FontSize="16" />
                            <TextBlock Grid.Column="2" Text="{Binding Remaining }" FontWeight="Bold" FontSize="16" />
                            <Button Grid.Column="3" Name="addButton" Click="addButton_Click" FontWeight="Bold" FontSize="16">+</Button>
                            <Button Grid.Column="4" Name="substractButton" Click="substractButton_Click" FontSize="16">-</Button>
                        </Grid>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

我的类具有 Name、Drinked 等属性。它在设置为 DataSource 的 List 中。这部分工作正常。

但是我需要向这个 ListBox 添加额外的条目,它将显示在 DataTemplate 之前。它不会有绑定或相同的结构 - 它将用作标题,并且将具有与 DataTemplate 不同的布局。 有什么办法吗?如果我像在普通 ListBox 中一样添加它,则会收到一个错误,即 ListBox 在使用绑定之前必须为空。

现在 ListBox 看起来像这样:

但我需要让它看起来像这样:

有可能吗?如果有办法使用 ListBox 以外的其他元素,我可以,只要我可以使用 Binding 和 DataTemplate。

【问题讨论】:

  • 你想让这个项目随着列表滚动吗?还是应该是静态的?
  • @ShawnKendrot 没关系

标签: c# wpf data-binding listbox


【解决方案1】:

如果scrollign 对你来说无关紧要,你可以简单地在你的列表框上方放置一个静态边框.. 对于要在滚动中包含该额外行的场景,您必须修改 ListBox 的模板。下面是一个隐式样式示例,它将在您的项目之前添加一个 TextBlock 并参与滚动:

        <Style TargetType="{x:Type ListBox}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBox}">
                        <ScrollViewer x:Name="ScrollViewer">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="I am an extra row" Grid.Row="0"/>
                                <ItemsPresenter Grid.Row="1"/>
                            </Grid>
                        </ScrollViewer>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

事实上,通过覆盖控件的模板,您可以为其提供所需的所有自定义项...您可以更改文本块以用于您想要的任何其他控件..

【讨论】:

    【解决方案2】:

    您可以通过使用 Stackpanel 或 Grid 来实现此目标。但是,如果您坚持在 ListBox 中使用额外的行,则可以使用内容模板选择器。在下面的解决方案中,我确实使用了一个触发器来根据其类型设置当前项目的模板。

        <Window.Resources>
        <local:ObjectToTypeConverter x:Key="ObjectToTypeConverter" />
    
        <ControlTemplate x:Key="emptyRow">
            <Grid HorizontalAlignment="Stretch">
                <Border Height="50" BorderBrush="Black" BorderThickness="2">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Extra row that is not part of the binding or DataTemplate" />
                </Border>
            </Grid>
        </ControlTemplate>
        <ControlTemplate x:Key="default">
                <Border BorderBrush="Black" BorderThickness="2">
                    <Grid Margin="4">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="3*" />
                            <ColumnDefinition Width="3*" />
                            <ColumnDefinition Width="3*" />
                            <ColumnDefinition Width="3*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="16"  />
                        <TextBlock Grid.Column="1" Text="{Binding Drinked }" FontWeight="Bold" FontSize="16" />
                        <TextBlock Grid.Column="2" Text="{Binding Remaining }" FontWeight="Bold" FontSize="16" />
                        <Button Grid.Column="3" Name="addButton" Click="addButton_Click" FontWeight="Bold" FontSize="16">+</Button>
                        <Button Grid.Column="4" Name="substractButton" Click="substractButton_Click" FontSize="16">-</Button>
                    </Grid>
                </Border>
        </ControlTemplate>
    
        <Style x:Key="ItemStyle" TargetType="{x:Type ListBoxItem}">
            <Setter Property="Template" Value="{DynamicResource emptyRow}" />
        <Style.Triggers>
                <DataTrigger Binding="{Binding ., Converter={StaticResource ObjectToTypeConverter}}" Value="{x:Type local:Model}">
                    <Setter Property="Template" Value="{DynamicResource default}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <Grid>
        <ListBox ItemsSource="{Binding}" BorderBrush="Transparent"
         Grid.IsSharedSizeScope="True"
         HorizontalContentAlignment="Stretch"
         Grid.Row="1"
         ItemContainerStyle="{StaticResource ItemStyle}"
         Grid.Column="0" Grid.ColumnSpan="4"
         Name="playerList" />
    </Grid>
    

    转换器只是将对象转换为它的类型

        public class ObjectToTypeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value?.GetType();
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    要将不同的对象添加到您的集合中,请将类型更改为 object 或根据您的继承设置更改为类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 2017-12-18
      • 2018-01-07
      • 2016-12-19
      • 1970-01-01
      相关资源
      最近更新 更多