c# - 画布上的 MVVM WPF 图像
问题描述
我有一个允许您在屏幕上创建对象的代码,有一个按钮面板,单击您在画布上创建图像/对象的按钮,我无法将另一个图像放置在 Canvas 中,以便可以将多个图像要显示,链接到以前创建的问题:WPF C# Display objects (2d Map)
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Canvas>
<Image x:Name="injWell" Source="/Resources/injectionWell.png"
HorizontalAlignment="Center" VerticalAlignment="Center"
Width="40" Height="40"
Stretch="Fill" StretchDirection="Both" IsHitTestVisible="False"/>
<Image x:Name="injWellNot" Source="/Resources/injectionWellNot.png"
HorizontalAlignment="Center" VerticalAlignment="Center"
Width="40" Height="40"
Stretch="Fill" StretchDirection="Both" IsHitTestVisible="False"/>
<TextBlock Canvas.Top="-20" Canvas.Left="-40" Width="100"
TextAlignment="Center" Text="{Binding Name}" FontWeight="Bold"
IsHitTestVisible="False"
Visibility="{Binding DataContext.ShowNames,
RelativeSource={RelativeSource FindAncestor, AncestorType=Window},
Converter={StaticResource BoolToVisibilityConverter}}"/>
<TextBlock Canvas.Left="30" Canvas.Top="10"
Text="{Binding X, StringFormat='{}X = {0}'}"
IsHitTestVisible="False"
Visibility="Collapsed" x:Name="XText"/>
<TextBlock Canvas.Left="30" Canvas.Top="25"
Text="{Binding Y, StringFormat='{}Y = {0}'}"
IsHitTestVisible="False"
Visibility="Collapsed" x:Name="YText"/>
</Canvas>
<ControlTemplate.Triggers>
<Trigger Property="IsDragging" Value="True">
<Setter TargetName="injWell" Property="Source" Value="/Resources/injectionWell.png"/>
<Setter TargetName="injWellNot" Property="Source" Value="/Resources/injectionWellNot.png"/>
</Trigger>
<DataTrigger Binding="{Binding DataContext.ShowAllCoordinates, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="True">
<Setter TargetName="XText" Property="Visibility" Value="Visible"/>
<Setter TargetName="YText" Property="Visibility" Value="Visible"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True"/>
<Condition Binding="{Binding DataContext.ShowCurrentCoordinates, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="XText" Property="Visibility" Value="Visible"/>
<Setter TargetName="YText" Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</DataTemplate>
解决方案
这里要实现的关键是您需要呈现项目列表,而在 MVVM 中,您可以使用 ItemsControl 来完成。(您也可以使用 ListView,但它们实现了您几乎肯定不会想要的附加功能,例如项目选择等)。最终,您希望所有图形对象都显示在 Canvas 上,因此您需要覆盖 ItemsPanel 属性并将其中一个放在 ItemsPanelTemplate 中。然后每个元素都需要定位在 Canvas 上,因此您需要设置 ItemContainerStyle 并在那里设置 Canvas.Left 和 Canvas.Top 属性(一个常见的错误是在元素本身上执行此操作,但它们会被放入一个容器,所以你必须这样做)。将所有这些放在一起,您将拥有如下所示的内容:
<ItemsControl ItemsSource="{Binding MyGraphicsViewModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
因此,MyGraphicsViewModels 通常是您创建的某个基类(例如 BaseGraphicsViewModel)的视图模型中的列表,然后您将其子类化为您想要绘制的所有不同类型的图形项。最后一个难题是添加 DataTemplates 以指定您希望每个视图模型类型如何在视图中表示:
<DataTemplate DataType="{x:Type vm:DerivedGraphicsObjectViewModel}">
<Rectangle Fill="Blue" Width="64" Height="64" />
</DataTemplate>
有关使用触发器而不是 DataTemplates 的更全面的示例,请查看我过去对这个 SO 问题的回答。
推荐阅读
- javascript - 在方法中制作json数组
- python - Groupby 使用参数应用/转换自定义函数 Pandas
- retrypolicy - 在重试场景中,客户端是否可以在第二次尝试重试后从第一次尝试中获取响应?
- sql-server - 使用 SqlPackage 提取 DB 导致“用户“someUser”登录失败”
- java - 如何在 Windows 上 JPackage RPM/PKG/DEB?
- spring-boot - spring cloud openfeign映射不起作用
- keycloak - Keycloak 注册会为重复的电子邮件引发 HTTP 500
- reactjs - 如何使用 redux、immer、react 从数组中删除元素
- kubernetes - 使用 CTR 导入图像会静默失败
- java - JaxB在soap请求中返回ElementNSImpl而不是对象,spring