2015-06-10 139 views
4

我一直在想如何将ObservableCollection<FrameworkElements>绑定到ItemsControl。我有一个现有的项目,严重依赖代码和画布的没有绑定,我试图更新使用mvvm和棱镜。将Shapes.Path项绑定到ItemsControl

ObservableCollection将被填充许多Path项。它们是从我使用的外部图书馆生成的。当我手动操作画布本身时,库正常工作。

下面是从视图模型的代码片段:

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> 

我遇到的问题是,路径从来没有画。任何关于我哪里出错的建议以及从哪里开始调试过程?

+0

原始实例工作,我只是在声明集合时忘记了'public'。 –

回答

0

ObservableCollection<FrameworkElement>是的,你可以在那里停下来。这不是MVVM。此外,您将项目模板定义为(空白,我想你可以说)路径对象。你不会将它绑定到你在可观察集合中抛出的路径的属性。

一个更好的实现是有一个ObservableCollection<string>包含路径数据,AKA the stuff that actually defines the path's shape,然后绑定到您的路径。

<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> 

如果您曾使用史努比来检查您在运行时的用户界面,你会看到你有很多路径的对象在那里,但他们都有空的数据。此外,如果您使用路径形状的血腥画布,则需要在路径上设置Canvas.LeftCanvas.Top附加属性。一个真正的MVVM的英雄将定义模型正是如此

public PathData{ 
    public double Left {get;set;} 
    public double Top {get;set;} 
    public string Data {get;set;} 
} 

然后在您的视图模型公开这些

public ObservableCollection<PathData> Items {get;private set;} 

然后您的路径与它们结合

<ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <Path Canvas.Left="{Binding Left}" 
       Canvas.Top="{Binding Top}" 
       Data="{Binding Data}"/> 
    </DataTemplate> 
</ItemsControl.ItemTemplate> 
+0

为什么当数据已经包含最终的corrdinates时设置Left和Top?没有左和顶,Canvas是非常有意义的,因为它不会缩放或翻译它的孩子。 – Clemens

+0

@Clemens他们呢?或者它们都将在画布中以0,0的原点进行渲染?如果你不使用画布来控制物品的位置,为什么要使用画布? – Will

+0

您正在通过Data属性中的Geometry控制位置。例如。中心在(100,100)处的椭圆几何。这不是呈现在(0,0),对不对? – Clemens

1

您的视图模型应该包含路径的抽象表示,例如

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 
}); 
+0

你正在ViewModel中创建UI并给我提供有关使用路径数据的信息吗?多德。 – Will

+0

@将在此视图模型中没有用户界面。只是几何形状和画笔,其中没有一个是UIElement。 – Clemens

+0

哈哈,几何是一个WPF类。好的,完成分裂的头发。先生,祝你好日子。 – Will

相关问题