将WPF Canvas子项绑定到ObservableCollection

sti*_*k81 13 .net data-binding wpf observablecollection

在我的WPF应用程序中,我有一个Canvas,在其中我做了一些绘图.之前我在后面的代码中处理了绘图,但现在我已经将所有内容都考虑在了ViewModel上.这给了我一些挑战..

我有一些持有笔划的InkPresenter对象.我在后面的代码中将它们作为子项添加到Canvas中 - 像这样:

// Build an InkPresenter: 
var someInkPresenter = BuildInkPresenter(..); 
//_myCanvas is the <Canvas> I want to display it in: 
_myCanvas.Children.Add(someInkPresenter); 
Run Code Online (Sandbox Code Playgroud)

现在 - 没有在持有_myCanvas的XAML的代码隐藏中构建InkPresenter我需要以不同的方式做到这一点.我想要做的是创建一个InkPresenter并将其添加到集合中:

public ObservableCollection<InkPresenter> Drawings;
Run Code Online (Sandbox Code Playgroud)

我现在的问题是如何将Canvas绑定到此ObservableCollection - 并在添加到集合时显示InkPresenters.我能以某种方式使用数据绑定来实现这一目标吗?

Anv*_*aka 19

我认为你可以用ItemsControl + ItemsPanelTemplate来做到这一点.像这样:

  <ItemsControl ItemsSource="{Binding YourCollection}">
    <ItemsControl.ItemsPanel>
     <ItemsPanelTemplate>
      <Canvas />
     </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
   </ItemsControl>
Run Code Online (Sandbox Code Playgroud)

要了解有关此方法的更多信息,请参阅Dr.WPF:ItemsControl:A到Z (P代表Panel)

  • 约翰,我在发布分歧之前尝试过这个:).InkPresenter是Canvas的直接子项.如果将UIElement添加到显式ItemsControl实例的Items集合中(而不是像ListBox这样的派生类的实例),它将成为items面板的直接子节点.如果添加了非UIElement,它将被包装在ContentPresenter中.请查看本文末尾的表格http://drwpf.com/blog/2008/03/25/itemscontrol-i-is-for-item-container. (3认同)
  • 这通常是您会采取的方法,但在这种情况下,您可能会遇到问题,因为 InkPresenter 不会像您在代码中添加它们时那样成为 Canvas 的直接子级。相反,视觉树将在每个 InkPresenter 项周围注入一个额外的 ContentPresenter。要使此方法发挥作用,您应该考虑从每个 InkPresenter 中提取实际数据(笔画)并将这些数据的集合存储在 VM 中。然后,您可以创建一个自定义 ItemsControl 来重写 GetContainerForItemOverride 以返回 InkPresenter。 (2认同)

Ken*_*_hj 14

Anvaka建议的解决方案很棒,但正如John Bowen指出你需要了解更多,如果你想将你的项目实际绑定到Canvas附加属性.

这是一个关于如何绑定到Canvas.Left和Canvas.Top的示例:

<ItemsControl ItemsSource="{Binding YourCollection}">
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <Canvas />
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
    <Style TargetType="ContentPresenter">
        <Setter Property="Canvas.Left" Value="{Binding YourModelLeft}" />
        <Setter Property="Canvas.Top" Value="{Binding YourModelTop}" />
    </Style>
</ItemsControl.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)

顺便说一句,在我尝试了Anvaka的建议之后,我找到了这个问题的解决方案,其中绑定不起作用.

希望这有助于其他人,寻找相同的答案.