【问题标题】:WPF - MVVM: how to draw a movable Rectangle with mouseWPF - MVVM:如何用鼠标绘制可移动的矩形
【发布时间】:2021-05-24 14:56:21
【问题描述】:

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

此时我实现了一个基本版本,用户可以通过单击按钮添加一个矩形(具有随机大小/位置)。这是实现此行为的 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 description here) 似乎不合适,因为缺少可能的交互(即按钮向上、移动);我应该考虑哪些替代方案?
  • 鼠标交互应该由绘制形状的画布处理还是由形状本身处理?
  • MVVM 是否适合用于此类应用程序?

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

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

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

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

    从您的设计来看,可能会给您带来麻烦的一个方面是您的 viewModel 管理 1 个形状。没错,但您需要另一个管理形状集合的 VM 层。它可以作为另一个类或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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多