使用MVVM / MVVMLight时简单绘图应用程序的代码结构

时间:2018-07-02 13:38:15

标签: c# wpf mvvm mvvm-light

我目前在我的一个应用中正在使用MVVM模式,更具体地说,我正在使用MVVMLight框架。在其中一个页面中,我将看到一个屏幕,用户可以在其中输入widthlength来绘制矩形,没有太多的代码逻辑,因此,我正在考虑将所有代码放入代码隐藏,因为此屏幕中将发生的大多数事与UI相关。

在这种情况下使用后台代码有意义吗?如果不是,您将如何构造代码以使用MVVM模式?在这种情况下,您将把什么放在ViewModel中,以及将代码放在什么后面?

这是不使用MVVM的代码。

XAML:

<Window x:Class="DrawingRectangles.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DrawingRectangles"
        mc:Ignorable="d"
        Title="MainWindow" Height="531.798" Width="782.115">
    <Grid Name="MyGrid" Width="480" Height="240" Margin="27,23,267,174">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="59*"/>
            <ColumnDefinition Width="421*"/>
        </Grid.ColumnDefinitions>
        <Canvas Name="MyCanvas" Background="#FFF1F0F0" Margin="10" Grid.ColumnSpan="2"/>

        <Grid Margin="10,235,10,-92" Background="WhiteSmoke" Grid.ColumnSpan="2">
            <Button x:Name="drawButton" Content="Draw"  Click="drawButton_Click"/>
            <Button x:Name="resetButton" Content="Reset" Click="resetButton_Click"/>
            <TextBox x:Name="textBoxPartWidth"/>
            <TextBox x:Name="textBoxPartLength"/>

        </Grid>
    </Grid>
</Window>

代码提示:

namespace DrawingRectangles
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void drawButton_Click(object sender, RoutedEventArgs e)
        {
            clearScreen();

            int xParts = 10;
            int yParts = 10;

            for (int i = 0; i < xParts; i++) {

                for (int j = 0; j < yParts; j++) {
                    // Create a rectangle.
                    Rectangle myRectangle = new Rectangle();
                    myRectangle.Width = Convert.ToDouble(textBoxPartLength.Text);
                    myRectangle.Height = Convert.ToDouble(textBoxPartWidth.Text);
                    myRectangle.Margin = new Thickness((Convert.ToInt32(myRectangle.Width) + 1) * i, (Convert.ToInt32(myRectangle.Height) + 1) * j, 0, 0);
                    myRectangle.Fill = new SolidColorBrush(Color.FromArgb(170, 51, 51, 255));
                    MyCanvas.Children.Add(myRectangle);
                }
            }
        }

        private void resetButton_Click(object sender, RoutedEventArgs e)
        {
            MyCanvas.Children.Clear();
        }

        private void clearScreen()
        {
            MyCanvas.Children.Clear();
        }
    }
}

UI

enter image description here

编辑: 第二张图片(仅供参考): enter image description here

1 个答案:

答案 0 :(得分:1)

视图中的Button应该绑定到视图模型的ICommand属性。单击Button时将执行该命令。请参阅this blog post,以获取有关如何在MVVM应用程序中处理事件的信息。在MvvmLight中,ICommand实现称为RelayCommand

您还应该将Text的{​​{1}}属性绑定到视图模型的两个源属性,并且视图中的TextBoxes元素应替换为Canvas您绑定到视图模型中定义的对象的集合。

请参考以下示例代码。

型号:

ItemsControl

查看:

public class Model
{
    public int Width { get; set; }
    public int Height { get; set; }
    public Thickness Margin { get; set; }
    public Brush Fill { get; set; }
}

查看模型

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Background="#FFF1F0F0" Margin="10" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="{Binding Width}" 
                       Height="{Binding Height}" 
                       Margin="{Binding Margin}"
                       Fill="{Binding Fill}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

<Button Content="Draw" Command="{Binding DrawCommand}" />
<Button Content="Reset" Command="{Binding ResetCommand}" />
<TextBox Text="{Binding Width}"/>
<TextBox Text="{Binding Height}"/>

在此示例中,所有应用程序逻辑均已移至其所属的视图模型。视图的代码隐藏类中没有逻辑。

还要注意,视图模型创建public class ViewModel { public ViewModel() { DrawCommand = new RelayCommand(Draw); ResetCommand = new RelayCommand(Clear); } public ObservableCollection<Model> Items { get; } = new ObservableCollection<Model>(); public RelayCommand DrawCommand { get; } public RelayCommand ResetCommand { get; } public int Width { get; set; } public int Height { get; set; } private void Draw() { Clear(); int xParts = 10; int yParts = 10; for (int i = 0; i < xParts; i++) { for (int j = 0; j < yParts; j++) { Model model = new Model(); model.Width = Width; model.Height = Height; model.Margin = new Thickness((model.Width + 1) * i, (model.Height + 1) * j, 0, 0); model.Fill = new SolidColorBrush(Color.FromArgb(170, 51, 51, 255)); Items.Add(model); } } } private void Clear() { Items.Clear(); } } 对象的实例,而不是创建Model元素。通常,在视图模型类中引用UI元素是一种不好的做法。 Rectangle元素由Rectangle创建。请在视图中查看ItemsControl