Структура кода для простых приложений рисования при использовании MVVM / MVVMLight - PullRequest
0 голосов
/ 02 июля 2018

В настоящее время я использую шаблон MVVM в одном из своих приложений, если быть более точным, я использую MVVMLight framework. На одной из страниц у меня будет экран, на котором пользователь может вводить width и length для рисования прямоугольников, не так много логики кода, поэтому я думал поместить весь свой код в код позади поскольку большая часть того, что будет происходить на этом экране, связана с пользовательским интерфейсом.

Имеет ли смысл использовать код в этом случае? Если нет, то как бы вы структурировали код для использования шаблона 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

EDIT: Второе изображение (только для справки): enter image description here

1 Ответ

0 голосов
/ 02 июля 2018

Button в представлении должно быть привязано к свойству ICommand модели представления. Команда будет выполнена, когда вы нажмете на Button. Пожалуйста, обратитесь к этой записи блога для получения информации о том, как обрабатывать события в приложении MVVM. В MvvmLight реализация ICommand называется RelayCommand.

Вам также следует связать свойства Text 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();
    }
}

В этом примере вся логика приложения была перемещена в модель представления, которой она принадлежит. В классе code-behind представления не осталось логики.

Также обратите внимание, что модели представлений создают экземпляры Model объектов, а не Rectangle элементов. Обычно считается плохой практикой ссылаться на элементы пользовательского интерфейса в классе модели представления. Элементы Rectangle создаются ItemsControl. См. ItemTemplate в представлении.

...