在我的WPF MVVM 应用程序中,我有ListBox
Canvas
作为其ItemsPanel
。 ListBox的项目是用户点击按钮时动态创建的 - ListBox.ItemsSource
是Elements
中存储的MainViewModel
(自定义类型)列表,即DataContext
我的MainWindow
。
目前,我的Element
类描述了具有X和Y坐标的简单对象(以便可以在我的ListBox的Canvas上绘制)和一些名为ShapeGeometry
的数据作为路径绘制。这是DataTemplate
:
<DataTemplate DataType="{x:Type localvm:Element}">
<Control IsEnabled="{Binding IsSelected,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}">
<Control.Template>
<ControlTemplate TargetType="Control">
<Viewbox Stretch="Uniform"> <!-- Paths need to be wrapped in a Canvas + Viewbox to be movable, stretchable and rotatable -->
<Canvas>
<Path x:Name="Path" Fill="#FFAA0000" Data="{Binding ShapeGeometry}" Stretch="Uniform"/>
</Canvas>
</Viewbox>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter TargetName="Path" Property="IsHitTestVisible" Value="False"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Control.Template>
</Control>
</DataTemplate>
如您所见,这允许我每个ListBoxItem只绘制一个特定的Path。相反,我希望我的ListBoxItem是一个包含ComplexElement
项列表的Element
,这意味着绘制的项目现在将包含不同数量的路径。现在,我关于如何实现这一目标的想法是将ListBoxItem
定义为ListBox
,ViewBox
+ Canvas
作为ItemsPanel
,就像在ListBoxItem
上一样上层,但它似乎过于复杂,或许可能被证明有点低效(我打算有几十个,如果不是几百个项目)。有更简单的方法吗?我可以以某种方式避免在每个{{1}}中使用ListBoxes吗?
答案 0 :(得分:0)
如果你想减少开销并拥有一个列表,你应该可以用一个DataGrid控件替换ListBox。
然后将Canvas添加到RowDetailsTemplate。或者您可以在RowDetailsTemplate中放置第二个ListBox。
答案 1 :(得分:0)
我建议您使用自定义控件(具有ListBox或任何您想要的)作为ListBox.ItemTemplate的DataTemplate。这样,您可以降低ListBox的复杂性,并且cutomized控件可以满足您的需求实现自己的逻辑。
public class MyListItem : Control
{
//Define the property/event/control logic you want
static MyListItem ()
{
//Remeber this to override the default style
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyListItem ), new FrameworkPropertyMetadata(typeof(MyListItem )));
}
}
<Style TargetType="{x:Type my:MyListItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type my:MyListItem}">
<Border>
<ListBox ItemsSource={Binding YourDetailList}>
<ListBox.ItemTemplate>
//Anything you want here
</ListBox.ItemTemplate>
</ListBox>
</Boder>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<my:MyListItem/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
1.我建议你不要使用canvas作为ListBox的ItemsPanel,它可能会禁用虚拟化,这可能会降低ItemsSource庞大时的性能。
2.似乎你想要一个嵌套的ListBox,所以如果ItemTemplate变化,你可以使用'ItemTemplateSelector',检查这个MSDN。但是记住选择器可能是'static',这意味着datatemplate可能在初始化时只选择一次。
3.此外,如果您希望Item在某些情况下更改自己的行为,请尝试使用模板中的触发器或在定义类中执行此操作。