首页 文章

将Shapes.Path项绑定到ItemsControl

提问于
浏览
4

我一直试图弄清楚如何将 ObservableCollection<FrameworkElements> 绑定到ItemsControl . 我有一个现有的项目,它严重依赖于后面的代码和canvas没有绑定,我试图更新以使用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>

我遇到的问题是Path永远不会画画 . 关于我哪里出错以及从哪里开始调试过程的任何建议?

2 回答

  • 1

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

    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

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

    更好的实现方法是使 ObservableCollection<string> 包含路径 data ,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>
    

    如果您在运行时使用过Snoop检查UI,那么您已经看到有很多Path对象,但它们都有空数据 .

    另外,如果您在路径形状中使用血腥画布,则需要在路径上设置 Canvas.LeftCanvas.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;}
    

    然后将你的路径绑定到它们

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

相关问题