c# - Canvas 上的MVVM WPF图像

标签 c# wpf visual-studio xaml mvvm

我有一个代码,可以让您在屏幕上创建对象,有一个按钮面板,单击按钮可以在 Canvas 上创建图像/对象,我无法将其他图像放置在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通常会在您的 View 模型中列出您已创建的某些基类(例如BaseGraphicsViewModel),然后将其子类化为您要绘制的所有不同类型的图形项。最后的难题是添加DataTemplates以指定您希望如何在 View 中表示每种 View 模型类型:
    <DataTemplate DataType="{x:Type vm:DerivedGraphicsObjectViewModel}">
            <Rectangle Fill="Blue" Width="64" Height="64" />
    </DataTemplate>

有关使用触发器而不是DataTemplates的更全面的示例,请查看过去的my answer to this SO question

关于c# - Canvas 上的MVVM WPF图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51516683/

相关文章:

c# - 制作 View 模型错误

c# - 任务等待困惑

c# - 使用 IDataErrorInfo 的 WPF MVVM 验证

c# - 如何处理项目计数检查器

visual-studio - 如何在 Visual Studio 2010 中使选定的 html 标记突出显示像在 Visual Studio 2008 中一样工作

c# - 对具有动态操作数的空合并运算符进行类型检查

c# - Nlog 和自定义级别

c# - SynchronizationContext.Current 在主线程上为空

c# - 在 .netcore 中使用同一个 nuget 包的多个版本

c++ - Visual C++ 创建缺少依赖项的 DLL