【问题标题】:Listbox style with items that contains lists具有包含列表的项目的列表框样式
【发布时间】:2020-11-04 09:00:26
【问题描述】:

我正在构建一个 webscaper 来抓取种子,后端已经完成,现在我有点卡在 UI 上(使用 WPF)。 我想在ListBox 上显示种子,但与查询相对应(我将其称为搜索词)。

传递给ListBox的数据是:

List<SearchTermData>

这是结构:

public class SearchTermData {
   public string SearchTerm { get; set; }
   public List<Torrent> Torrents { get; set; } = new List<Torrent>();
}

Torrent 是这样的:

public class Torrent {
   public string Name { get; set; }
   public string Size { get; set; }
}

我通常希望ListBox 显示Grid。第 1 列是“SearchTerm”,第 2 列是“Torrents”的StackPanel (List&lt;Torrent&gt;)。

它正确显示“SearchTermData”,带有SearchTerm 名称和一般结构,但无法显示Torrents 的StackPanel。

这是我的 XAML 风格:

<Style x:Key="TorrentListbox" TargetType="ListBox">
   <Setter Property="UseLayoutRounding" Value="True" />
   <Setter Property="BorderThickness" Value="0" />
   <Setter Property="BorderBrush" Value="{StaticResource Black}"/>
   <Setter Property="Background" Value="Transparent" />
   <Setter Property="FontFamily" Value="{StaticResource DefaultFont}" />
   <Setter Property="FontWeight" Value="Regular" />
   <Setter Property="HorizontalContentAlignment" Value="Left" />
   <Setter Property="SelectionMode" Value="Multiple" />
   <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
   <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
   <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
   <Setter Property="ItemContainerStyle" Value="{DynamicResource TermItem}" />
</Style>

<Style x:Key="TermItem" TargetType="ListBoxItem">
   <Setter Property="SnapsToDevicePixels" Value="True" />
   <Setter Property="OverridesDefaultStyle" Value="True" />
   <Setter Property="BorderThickness" Value="2"/>
   <Setter Property="BorderBrush" Value="{StaticResource DSGray}"/>
   <Setter Property="Foreground" Value="{StaticResource Black}" />
   <Setter Property="FontFamily" Value="{StaticResource DefaultFont}" />
   <Setter Property="FontWeight" Value="Regular" />
   <Setter Property="FontSize" Value="16" />
   <Setter Property="Margin" Value="0,0,0,4"/>
   <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
   <Setter Property="UseLayoutRounding" Value="True" />
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="ListBoxItem">
            <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="0" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
               <Grid Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Visibility="Visible">
                  <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="Auto"/>
                     <ColumnDefinition Width="*"/>
                  </Grid.ColumnDefinitions>
                  <Grid.RowDefinitions>
                     <RowDefinition Height="*"/>
                  </Grid.RowDefinitions>
                  <Label Content="{Binding Path=SearchTerm}" BorderThickness="0,0,2,0" BorderBrush="{StaticResource Black}" Style="{StaticResource KeyLabel}" Foreground="{StaticResource DSGreen}" FontWeight="Bold" VerticalContentAlignment="Top" Grid.Row="0" Grid.Column="0"/>
                  <StackPanel Grid.Row="0" Grid.Column="1">
                     <ItemsControl ItemsSource="{Binding Path=Torrents}">
                        <ItemsControl.ItemTemplate>
                           <DataTemplate>
                              <Border BorderThickness="1" BorderBrush="{StaticResource DSGreen}">
                                 <ItemsControl ItemsSource="{Binding Torrent}">
                                    <ItemsControl.ItemTemplate>
                                       <DataTemplate>
                                          <Grid HorizontalAlignment="Stretch" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Visibility="Visible">
                                             <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*"/>
                                                <ColumnDefinition Width="Auto"/>
                                                <ColumnDefinition Width="Auto"/>
                                             </Grid.ColumnDefinitions>
                                             <Grid.RowDefinitions>
                                                <RowDefinition Height="*"/>
                                             </Grid.RowDefinitions>
                                             <Label Content="{Binding Path=Name}" Style="{StaticResource PropertyLabel}" Grid.Row="0" Grid.Column="0"/>
                                             <Label Content="Size:" Style="{StaticResource KeyLabel}" Grid.Row="0" Grid.Column="1"/>
                                             <Label Content="{Binding Path=Size}" Style="{StaticResource PropertyLabel}" Grid.Row="0" Grid.Column="2"/>
                                          </Grid>
                                       </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                 </ItemsControl>
                              </Border>
                           </DataTemplate>
                        </ItemsControl.ItemTemplate>
                     </ItemsControl>
                  </StackPanel>
               </Grid>
            </Border>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

如果有人能帮我解决这个问题,我将不胜感激!

【问题讨论】:

    标签: c# wpf xaml binding


    【解决方案1】:

    在Torrent 的项目模板中,有一个不需要的嵌套ItemsControl,它绑定到Torrent 类型项目上的属性Torrent,该项目不存在。

    <ItemsControl ItemsSource="{Binding Torrent}">
    

    下面的控件模板应该可以工作。我删除了多余的ItemsControl 和StackPanel,因为它只包含一个控件,这就是你不需要它的原因。

    <ControlTemplate TargetType="ListBoxItem">
       <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="0" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
          <Grid Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Visibility="Visible">
             <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
             </Grid.ColumnDefinitions>
             <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
             </Grid.RowDefinitions>
             <Label Content="{Binding Path=SearchTerm}" BorderThickness="0,0,2,0" BorderBrush="{StaticResource Black}" Style="{StaticResource KeyLabel}" Foreground="{StaticResource DSGreen}" FontWeight="Bold" VerticalContentAlignment="Top" Grid.Row="0" Grid.Column="0"/>
             <ItemsControl Grid.Row="0" Grid.Column="1" ItemsSource="{Binding Path=Torrents}">
                <ItemsControl.ItemTemplate>
                   <DataTemplate>
                      <Border BorderThickness="1" BorderBrush="{StaticResource DSGreen}">
                         <Grid HorizontalAlignment="Stretch" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Visibility="Visible">
                            <Grid.ColumnDefinitions>
                               <ColumnDefinition Width="*"/>
                               <ColumnDefinition Width="Auto"/>
                               <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                               <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Label Content="{Binding Path=Name}" Style="{StaticResource PropertyLabel}" Grid.Row="0" Grid.Column="0"/>
                            <Label Content="Size:" Style="{StaticResource KeyLabel}" Grid.Row="0" Grid.Column="1"/>
                            <Label Content="{Binding Path=Size}" Style="{StaticResource PropertyLabel}" Grid.Row="0" Grid.Column="2"/>
                         </Grid>
                      </Border>
                   </DataTemplate>
                </ItemsControl.ItemTemplate>
             </ItemsControl>
          </Grid>
       </Border>
    </ControlTemplate>
    

    将 ListView 与 GridView 结合使用的替代方法

    由于您想显示两列,您也可以将ListView 与GridView 结合使用。这样,您实际上将拥有 real 列。

    <ListView ItemsSource="{Binding SearchTerms}">
       <ListView.ItemContainerStyle>
          <Style TargetType="ListViewItem">
             <Setter Property="SnapsToDevicePixels" Value="True" />
             <Setter Property="OverridesDefaultStyle" Value="True" />
             <Setter Property="BorderThickness" Value="2"/>
             <Setter Property="BorderBrush" Value="{StaticResource DSGray}"/>
             <Setter Property="Foreground" Value="{StaticResource Black}" />
             <Setter Property="FontFamily" Value="{StaticResource DefaultFont}" />
             <Setter Property="FontWeight" Value="Regular" />
             <Setter Property="FontSize" Value="16" />
             <Setter Property="Margin" Value="0,0,0,4"/>
             <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
             <Setter Property="UseLayoutRounding" Value="True" /> 
             <Setter Property="VerticalContentAlignment" Value="Stretch" />
             <Setter Property="HorizontalContentAlignment" Value="Stretch" />
             <Setter Property="Template">
                <Setter.Value>
                   <ControlTemplate TargetType="{x:Type ListViewItem}">
                      <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="0" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                         <GridViewRowPresenter/>
                      </Border>
                   </ControlTemplate>
                </Setter.Value>
             </Setter>
          </Style>
       </ListView.ItemContainerStyle>
       <ListView.View>
          <GridView>
             <GridViewColumn Header="Search Term">
                <GridViewColumn.CellTemplate>
                   <DataTemplate>
                      <Label Content="{Binding Path=SearchTerm}" BorderThickness="0,0,2,0" BorderBrush="Black" Foreground="Green" FontWeight="Bold"/>
                   </DataTemplate>
                </GridViewColumn.CellTemplate>
             </GridViewColumn>
             <GridViewColumn Header="Torrents">
                <GridViewColumn.CellTemplate>
                   <DataTemplate>
                      <ItemsControl ItemsSource="{Binding Torrents}">
                         <ItemsControl.ItemTemplate>
                            <DataTemplate>
                               <Border BorderThickness="1" BorderBrush="Green">
                                  <Grid HorizontalAlignment="Stretch" UseLayoutRounding="{TemplateBinding UseLayoutRounding}" Visibility="Visible">
                                     <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="Auto"/>
                                     </Grid.ColumnDefinitions>
                                     <Grid.RowDefinitions>
                                        <RowDefinition Height="*"/>
                                     </Grid.RowDefinitions>
                                     <Label Content="{Binding Path=Name}" Grid.Row="0" Grid.Column="0"/>
                                     <Label Content="Size:" Grid.Row="0" Grid.Column="1"/>
                                     <Label Content="{Binding Path=Size}" Grid.Row="0" Grid.Column="2"/>
                                  </Grid>
                               </Border>
                            </DataTemplate>
                         </ItemsControl.ItemTemplate>
                      </ItemsControl>
                   </DataTemplate>
                </GridViewColumn.CellTemplate>
             </GridViewColumn>
          </GridView>
       </ListView.View>
    </ListView>
    

    【讨论】:

    • 好的,所以首先我尝试使用第一个选项而不是我自己的选项,它确实显示了种子,但 List 基本上受 Term 的大小限制。简而言之,我试图生成一个包含 5 个术语的测试列表,每个术语有 20 个种子。在当前窗口大小中,Term 仅显示 17 个 Torrent,如果我向下滚动,而不是显示其余部分,它会移动到下一个学期。知道为什么吗?
    • 我也想试试你建议的 ListView 模板,但我需要它作为一种样式,因为它在多个窗口和文件中使用...我尝试将其修改为自己的样式但不熟悉 Listview ,我没有取得太大的成功。
    • @DavidShnayder 滚动问题是由默认的逻辑滚动引起的。这意味着按项目滚动,而不是像素。请参阅此related post 或this one,了解如何停用它。
    • @DavidShnayder 至于第二种方法中提取样式,您可以将项目容器样式和单元格数据模板移出并共享到资源字典中。
    • 感谢您的所有帮助伙伴!我真的学到了很多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多