使用 ItemsPanelTemplate 时的 DisplayMemberPath
DisplayMemberPath when using ItemsPanelTemplate
我有一个 SomeObject 类型的对象列表,其定义如下:
public struct SomeObject
{
public SomeObject(int id, string imgPath)
{
Id = id;
ImagePath = imgPath;
}
public int Id;
public string ImagePath;
}
我想在列表框中显示这些对象,每个对象显示一个图像并将它们排列在平铺布局中。
ItemsTemplate 只是一个图像。
ItemsPanelTemplate 是一个 TilePanel。
当我只使用字符串(图像路径)而不是 SombeObject 项目作为列表项时,一切正常并且图像显示正确。
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended"
SelectionChanged="OnItemSelectionChanged"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=SomeObjectsCollectionView, UpdateSourceTrigger=PropertyChanged}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source ="{Binding}"
VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" >
</Image>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<controls:VirtualizingTilePanel ChildSize="{Binding
RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemSize, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
使用 SomeObject 项目时,此代码为我提供了一个图块列表,但未显示图像。
System.Windows.Data 错误:40:BindingExpression 路径错误:'ImagePath' 属性 未在 'object' ''SomeObject' 上找到
(哈希码=1739718653)'。 BindingExpression:Path=图片路径; DataItem='SomeObject' (HashCode=1739718653);
目标元素是 'Image' (Name='');目标 属性 是 'Source'(类型 'ImageSource')
这是预料之中的,因为我还没有告诉控件,究竟要显示什么(SomeObject 的 属性)。
除了 ItemsPanelTemplate 之外,使用 DisplayMemberPath 也不起作用,那么如何设置 属性 用于在图像中显示?
感谢您的帮助!
编辑:
@nkoniishvt
这听起来确实是正确的方法,但我无法让它正常工作。我做错了什么?
我在后面的UserControl代码中添加了这个DP:
public static readonly DependencyProperty ItemsTemplateProperty =
DependencyProperty.Register("ItemsTemplate",
typeof(DataTemplate),
typeof(VerticalTileBox),
new PropertyMetadata(null));
public DataTemplate ItemsTemplate
{
get {return (DataTemplate)GetValue(ItemsTemplateProperty);}
set {SetValue(ItemsTemplateProperty, value);}
}
并像这样更改了 xaml:
<ListBox
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended"
SelectionChanged="OnItemSelectionChanged"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemCollection, UpdateSourceTrigger=PropertyChanged}"
ItemTemplate="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemsTemplate, UpdateSourceTrigger=PropertyChanged}"
>
<ItemsPanelTemplate>
<controls:VirtualizingTilePanel ChildSize="{Binding
RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemSize, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
数据模板定义如下:
<DataTemplate x:Name="SomeImageItemTemplate" DataType="utilities:SomeObject">
<Image Source ="{Binding Path=ImagePath}"
VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" />
</DataTemplate>
在我看来,整体的使用方式是这样的:
<ctrls:VerticalTileBox Source="{Binding ImageListView, UpdateSourceTrigger=PropertyChanged}" ItemsTemplate="{DynamicResource SomeImageItemTemplate}"/>
结果是显示了图块,但除了对象的 class 名称 (SomeObject) 之外它们都是空的。
如果您作为 ListBox 的 ItemsSource 放置的数据未知并且您的 UserControl 必须保持通用,则您不能拥有通用 DataTemplate。
您应该让您的 UserControl 的使用者提供 DataTemplate,或者在 UserControl.Resources 中,或者在您需要创建并绑定到 ListBox 的 ItemTemplate 的 DataTemplate DP 中。
面板不应说明子项的显示方式,而应说明其应显示的位置和大小。
我有一个 SomeObject 类型的对象列表,其定义如下:
public struct SomeObject
{
public SomeObject(int id, string imgPath)
{
Id = id;
ImagePath = imgPath;
}
public int Id;
public string ImagePath;
}
我想在列表框中显示这些对象,每个对象显示一个图像并将它们排列在平铺布局中。 ItemsTemplate 只是一个图像。 ItemsPanelTemplate 是一个 TilePanel。
当我只使用字符串(图像路径)而不是 SombeObject 项目作为列表项时,一切正常并且图像显示正确。
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended"
SelectionChanged="OnItemSelectionChanged"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=SomeObjectsCollectionView, UpdateSourceTrigger=PropertyChanged}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source ="{Binding}"
VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" >
</Image>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<controls:VirtualizingTilePanel ChildSize="{Binding
RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemSize, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
使用 SomeObject 项目时,此代码为我提供了一个图块列表,但未显示图像。
System.Windows.Data 错误:40:BindingExpression 路径错误:'ImagePath' 属性 未在 'object' ''SomeObject' 上找到 (哈希码=1739718653)'。 BindingExpression:Path=图片路径; DataItem='SomeObject' (HashCode=1739718653); 目标元素是 'Image' (Name='');目标 属性 是 'Source'(类型 'ImageSource')
这是预料之中的,因为我还没有告诉控件,究竟要显示什么(SomeObject 的 属性)。 除了 ItemsPanelTemplate 之外,使用 DisplayMemberPath 也不起作用,那么如何设置 属性 用于在图像中显示?
感谢您的帮助!
编辑: @nkoniishvt
这听起来确实是正确的方法,但我无法让它正常工作。我做错了什么?
我在后面的UserControl代码中添加了这个DP:
public static readonly DependencyProperty ItemsTemplateProperty =
DependencyProperty.Register("ItemsTemplate",
typeof(DataTemplate),
typeof(VerticalTileBox),
new PropertyMetadata(null));
public DataTemplate ItemsTemplate
{
get {return (DataTemplate)GetValue(ItemsTemplateProperty);}
set {SetValue(ItemsTemplateProperty, value);}
}
并像这样更改了 xaml:
<ListBox
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended"
SelectionChanged="OnItemSelectionChanged"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemCollection, UpdateSourceTrigger=PropertyChanged}"
ItemTemplate="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemsTemplate, UpdateSourceTrigger=PropertyChanged}"
>
<ItemsPanelTemplate>
<controls:VirtualizingTilePanel ChildSize="{Binding
RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemSize, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
数据模板定义如下:
<DataTemplate x:Name="SomeImageItemTemplate" DataType="utilities:SomeObject">
<Image Source ="{Binding Path=ImagePath}"
VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" />
</DataTemplate>
在我看来,整体的使用方式是这样的:
<ctrls:VerticalTileBox Source="{Binding ImageListView, UpdateSourceTrigger=PropertyChanged}" ItemsTemplate="{DynamicResource SomeImageItemTemplate}"/>
结果是显示了图块,但除了对象的 class 名称 (SomeObject) 之外它们都是空的。
如果您作为 ListBox 的 ItemsSource 放置的数据未知并且您的 UserControl 必须保持通用,则您不能拥有通用 DataTemplate。
您应该让您的 UserControl 的使用者提供 DataTemplate,或者在 UserControl.Resources 中,或者在您需要创建并绑定到 ListBox 的 ItemTemplate 的 DataTemplate DP 中。
面板不应说明子项的显示方式,而应说明其应显示的位置和大小。