WPF:为ListBox绑定设置绑定属性

13
我有一个ListBox,我将ItemsSource绑定到存储在DataContext对象中的集合。这使得使用ToString()函数显示列表。
<ListBox ItemsSource="{Binding SomeCollection}"></ListBox>                    

现在我想显示集合中对象的属性。因此,我想定义一个模板等来处理绑定列表中所有对象的属性。我尝试了各种不同的方法,但都没有成功。我想做类似于这样的事情:

<ListBox ItemsSource="{Binding SomeCollection}">
    <ListBox.Template>
        <ControlTemplate>                                
            <ListViewItem Content="{Binding ThePropertyOnElm}"></ListViewItem>
        </ControlTemplate>
    </ListBox.Template>
</ListBox>

有人能帮我把这个改正吗?


你是在说 ThePropertyOnElm 是一个运行时的值,可以动态地更改以改变在列表框中显示的项目吗? - Drew Noakes
如果我表达不够清晰,我很抱歉。我的意思是SomeCollection是一个ObservableCollection<MyElm>,而MyElm有一个属性ThePropertyOnElm,我希望在ListBox中显示该属性,而不是MyElm的ToString()函数返回的内容。 - stiank81
4个回答

37

你不需要指定一个模板,你可以直接使用DisplayMemberPath属性,像这样:

<ListBox ItemsSource="{Binding SomeCollection}" DisplayMemberPath="ThePropertyOnElm" />

希望这可以帮助到你!


12

我认为这就是你想要做的:

<ListBox ItemsSource="{Binding SomeCollection}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type local:YourDataType}">                                
            <TextBlock Text="{Binding ThePropertyOnElm}" />
        </ControlTemplate>
    </ListBox.ItemTemplate>
</ListBox>

ListBox的模板将会修改实际列表框的外观,而ItemTemplate将会控制列表框中每个单独项目的外观。我把ControlTemplate改成了DataTemplate,并将其分配给YourDataType类型。此外,我在数据模板中使用了TextBlock,而不是ListBoxItem。因为DataTemplate被分配给了ListBoxItem(应该包含某种内容,而不是另一个ListBoxItem)。

我还没有尝试编译这段代码,所以可能不完全正确。如果有问题,请告诉我,我会采取额外的步骤!


Roel已经做到了,但如果您最终需要使其更复杂,例如在模板中显示多个属性,请使用此方法。 - Mark Synowiec
这看起来就像我想要的 - 直到Roel给出了更简单的解决方案,是的。如果我需要做更复杂的事情,我会将其保留以供以后参考。谢谢! - stiank81

2
使用路径绑定属性:

使用路径绑定属性:

<ListBox ItemsSource="{Binding SomeCollection}">
    <ListBox.Template>
        <ControlTemplate>                                
            <ListViewItem Content="{Binding Path=ThePropertyOnElm}"></ListViewItem>
        </ControlTemplate>
    </ListBox.Template>
</ListBox>

注意:这个有些令人困惑的名称(Path)之所以如此,是因为它可以扩展到子属性等。因此,如果ThePropertyOnElm属性返回一个带有名为Name的属性的对象,您可以编写{Binding Path=ThePropertyOnElm.Name}等等。

不,那并没有帮助。无论如何;我认为在像这样的简单绑定中,路径是可选的,因为你只需要指定路径。因此 - 你的例子和我的一样。不是吗? - stiank81
@Tor,我认为这与问题中所要求的没有任何不同。BindingPath属性是默认的内容属性,这意味着您不必像您建议的那样明确地包含它。但我认为原始问题对所需内容并不是很清楚。 - Drew Noakes

1

这是我最近在Code Project上发布的一个示例:

    <Window
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2006" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
      x:Class="GameSampleApp.Window1"
      x:Name="Window"
      Title="Sample App"
      Width="380" Height="240">
      <Window.Resources>
        <Style TargetType="ListBox">
          <Setter Property="Control.FontFamily" Value="Tahoma" />
          <Setter Property="Control.FontSize" Value="10" />
        </Style>
        <Style x:Key="FontStyle">
          <Setter Property="Control.FontFamily" Value="Verdana" />
          <Setter Property="Control.FontStyle" Value="Italic" />
          <Setter Property="Control.FontSize" Value="12"/>
        </Style>
        <DataTemplate x:Key="GamePersonTemplate">
          <Grid>
            <Grid.RowDefinitions>
              <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
              <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <TextBlock Width="40" Grid.Column="0" Text="{Binding Name, Mode=OneWay}" />
          </Grid>
        </DataTemplate>
      </Window.Resources>
      <Grid x:Name="LayoutRoot">
      <ListBox Padding="3" HorizontalAlignment="Left" Width="Auto" 
          ItemTemplate="{DynamicResource GamePersonTemplate}" 
          ItemsSource="{Binding}" VerticalAlignment="Top" Height="Auto"/>
      </Grid>
  </Window>

在这个示例中,我将ItemsSource设置为指向数据上下文绑定,该绑定可以位于可视树的任何位置。项目模板在Window.Resources中定义,但也可以在单独的ResourceDictionary中定义。基本上,这个项目模板将为每个项目行显示一个单独的文本块,但如果需要,它也可以被制作得更加复杂;这就是WPF的美妙之处。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接