繁体   English   中英

WPF - MVVM:如何用鼠标绘制可移动的矩形

[英]WPF - MVVM: how to draw a movable Rectangle with mouse

我是 WPF 的新手,我想使用 MVVM 模式创建一个程序(不使用 MvvmLight 等外部库)。 该应用程序允许用户使用鼠标在 canvas 内绘制矩形(以及将来的其他形状)(类似于 Windows 绘图,只是为了清楚起见)。 用户也可以使用鼠标交互来移动/调整创建的矩形。

此时我实现了一个基本版本,用户可以通过单击按钮添加一个矩形(具有随机大小/位置)。 这是实现此行为的 MainWindow 视图的代码:

    ...
    Title="{Binding Path=Titolo}"
    Height="450" Width="800"
    d:DataContext="{d:DesignInstance vm:MainWindowViewModel}">


<StackPanel>
    <StackPanel Orientation="Horizontal">
        <Button Content="Add Rectangle" Command="{Binding AddShapeCommand}" />
    </StackPanel>
    <Canvas>
        <ItemsControl ItemsSource="{Binding AllShapeCollection}">
            <ItemsControl.Resources>
                <DataTemplate DataType="{x:Type vm:MyRectViewModel}">
                    <uc:MyRectView/>
                </DataTemplate>
            </ItemsControl.Resources>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        

            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Canvas.Left" Value="{Binding xLT}"  />
                    <Setter Property="Canvas.Top" Value="{Binding yLT}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </Canvas>
</StackPanel>

Usercontrol MyRectView 定义如下:

<UserControl x:Class="MVVM_TestRect.Views.MyRectView"
         ...
         xmlns:vm="clr-namespace:MVVM_TestRect.ViewModels"
         xmlns:local="clr-namespace:MVVM_TestRect.Views"
         mc:Ignorable="d" 
         d:DataContext="{d:DesignInstance vm:MyRectViewModel}"
         Width="auto" Height="auto">
   <Grid>
       <Rectangle Width="{Binding Path=Width, Mode=TwoWay}"
               Height="{Binding Path=Height, Mode=TwoWay}"
               Fill="Green"/>
   </Grid>
</UserControl>

该程序按方面工作,并且绑定似乎没问题。

现在,如前所述,我将使用鼠标和移动/调整形状的能力来实现绘图。 我找到了很多例子,但没有人能解决我的疑问:

  • MVVM 模式不允许将事件处理程序(用于鼠标交互)放在视图代码隐藏中,那么我应该在哪里编写事件处理程序?
  • 由于缺少可能的交互(即按钮向上、移动),MouseAction( 此处为 msdn 描述)似乎不合适; 我应该考虑哪些替代方案?
  • 鼠标交互应该由绘制形状的地方还是由形状本身处理?
  • MVVM 是用于此类应用程序的正确模式吗?

MVVM 模式只是将视觉设计与应用程序数据结构分开的理想模式,所以当您说“MVVM 模式不允许将事件处理程序(用于鼠标交互)置于代码隐藏视图中”时,这可能过于激烈。 尝试坚持下去以获得更好的设计,但一开始不要太疯狂。 看看这个页面,它可能会很有趣。

WPF 在后面的代码中自动为您创建事件处理程序,所以这就是它们的位置。 您可能想要做的是,而不是直接在事件处理程序中修改数据,将有一个 ViewModel,其方法将帮助您修改数据。

您可以使用与 Canvas 关联的PreviewMouse(Up,Down,Move)事件。 这可能比尝试单击您的形状更容易,特别是当多个形状可能重叠时。 显然,如果您有许多形状,则必须有一种方法可以知道要编辑哪些形状(通过 combobox 手动选择,找到关闭形状以单击鼠标等)

从您的设计来看,可能会给您带来麻烦的一个方面是您的 viewModel 管理1 个 shape 没错,但您需要另一个管理形状集合的 VM 层。 它可以作为另一个 class 或作为 MyRectViewModel 中的一组MyRectViewModel方法来完成:


  void MyCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
  { 
       MyShapeCollectionViewModel.StoreMouseDown(e);
  }

  void MyCanvas_PreviewMouseMove(object sender, MouseButtonEventArgs e)
  { 
       MyShapeCollectionViewModel.ModifyShapes(e);
  }
    
  void MyCanvas_PreviewMouseUp(object sender, MouseButtonEventArgs e)
  { 
       MyShapeCollectionViewModel.ModifyShapes(e);
  }

ModifyShapes()将计算鼠标拖动,找到要编辑的形状并调用其编辑方法。 然后,一旦修改了 shape 数据,就会触发相应的事件来更新关联的 View

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM