绑定的形状.将项路径到ItemsControl
本文关键字:路径 ItemsControl 绑定 | 更新日期: 2023-09-27 17:54:55
我一直在试图找出如何将ObservableCollection<FrameworkElements>
绑定到ItemsControl。我有一个现有的项目,严重依赖于代码背后和画布的没有绑定,我试图更新使用mvvm和prism。
ObservableCollection将被许多Path项填充。它们是从我使用的外部库生成的。当我手动操作画布本身时,库的功能是正确的。
下面是ViewModel的代码片段:
ObservableCollection<FrameworkElement> _items;
ObservableCollection<FrameworkElement> Items
{
get { return _items; }
set
{
_items = value;
this.NotifyPropertyChanged("Items");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
支持XAML <ItemsControl ItemsSource="{Binding Items}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="canvas" IsItemsHost="True">
<Canvas.Background>
<SolidColorBrush Color="White" Opacity="100"/>
</Canvas.Background>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我所经历的问题是,路径从来没有绘制。任何建议在哪里我错了,从哪里开始调试过程?
你的视图模型应该包含一个路径的抽象表示,例如
public class PathData
{
public Geometry Geometry { get; set; }
public Brush Fill { get; set; }
public Brush Stroke { get; set; }
public double StrokeThickness { get; set; }
// ... probably more Stroke-related properties
}
如果你现在有一个像
这样的PathData对象集合public ObservableCollection<PathData> Paths { get; set; }
你的ItemsControl可以有一个ItemsTemplate,如下所示:
<ItemsControl ItemsSource="{Binding Paths}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding Geometry}" Fill="{Binding Fill}"
Stroke="{Binding Stroke}" StrokeThickness="{Binding StrokeThickness}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
你现在应该像这样添加PathData实例:
Paths.Add(new PathData
{
Geometry = new RectangleGeometry(new Rect(100, 100, 100, 100)),
Fill = Brushes.AliceBlue,
Stroke = Brushes.Red,
StrokeThickness = 2
});
ObservableCollection<FrameworkElement>
是的,你可以停在这里。这不是MVVM。此外,您还将项目模板定义为(我猜您可以说是空的)路径对象。你不能把它绑定到你的可观察对象集合中抛出的路径的属性中。
一个更好的实现是有一个ObservableCollection<string>
包含路径data, AKA的东西,实际上定义了路径的形状,然后绑定这个到你的路径。
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="canvas" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
如果你在运行时使用Snoop检查你的UI,你会发现你有很多Path对象,但是它们都是空数据。
也同样,如果你使用画布的路径形状,你需要设置Canvas.Left
和Canvas.Top
附加属性在你的路径。一个真正的MVVM英雄应该这样定义一个模型
public PathData{
public double Left {get;set;}
public double Top {get;set;}
public string Data {get;set;}
}
然后在ViewModel
中公开这些public ObservableCollection<PathData> Items {get;private set;}
然后将您的Path绑定到它们
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Canvas.Left="{Binding Left}"
Canvas.Top="{Binding Top}"
Data="{Binding Data}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>