• WPF – MVVM: how to draw a movable Rectangle with mouse(根据不同的实例画不同的图形)


    原文:WPF - MVVM: how to draw a movable Rectangle with mouse - TechInPlanet
    Asked By: Anonymous

    I’m new on WPF and I want to create a program using MVVM pattern (without using external library like MvvmLight). The application let the user to draw rectangles (and other shapes in future) inside canvas using mouse (similar to Windows Paint, just to be clear). The user could move/resize created rectangles using mouse interaction as well.

    At this moment I implemented a basic version in which the user can add a rectangle (with random size/position) by clicking a button. This is the code of the MainWindow view which implement this behaviour:

        ...
        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 is defined as follow:

    <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>
    

    The program works as aspected and binding appears to be ok.

    Now, as described before, I would to implement the drawing with mouse and the ability to move/resize shapes.
    I found many example but no one can resolve my doubts:

    • MVVM pattern doesn’t allow to put event handler (for mouse interaction) in view code-behind, so where should I write event handlers?
    • MouseAction (msdn description here) appears to not be appropriate because of lack of possible interacion (i.e. button up, move); what alternatives should I consider?
    • the mouse interaction should be handled by che canvas where the shape are drawn or by the shape itself?
    • MVVM is the right pattern to use for this kind of application?

    Solution

    Answered By: Anonymous

    MVVM pattern is just a desired pattern to separate visual design from applicaton data structure, so when you say "MVVM pattern doesn’t allow to put event handler (for mouse interaction) in view code-behind" maybe that is being too drastic. Try to stick to it for better designs but don’t get too crazy at the beginning. Have a look at this page, it might be of interest.

    WPF creates automatically the event handlers for you in the code behind, so that is the place for them. What you may want to do is to, instead of modifying your data directly inside your event handler, there will be a ViewModel whose methods will help you modify your data.

    You can use the PreviewMouse(Up,Down,Move) events associated to the Canvas. It might be easier than trying to click on your shape, specially when several shapes may overlap. Obviously, if you have many shapes, there must be a way to know which shapes is going to be edited (manual selection through combobox, finding the closes shape to mouse click, etc)

    From your design, one aspect that may give you some trouble is the fact that your viewModel manages 1 shape. It isn’t wrong, but you need another VM layer that manages a collection of shapes. It can be done as another class or as a bunch of static methods in your 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);
      }
    
    

    Where ModifyShapes() will calculate the mouse drag, find the shape to be edited and invoke its edition methods. Then, once the shape data is modified, the corresponding event will be fired to update the associated View

  • 相关阅读:
    UG二次开发-CAM-获取修改路径参数
    多线程01
    MFC的对话框使用Scintilla
    CATIA的后处理
    win32窗体中使用Scintilla窗体
    string的reserve和resize
    前端宝典
    MarkDown学习
    JAVA中构造方法总结
    IDEA中maven和tomcat的配置
  • 原文地址:https://www.cnblogs.com/bruce1992/p/16646995.html
Copyright © 2020-2023  润新知