Как предоставить и передать «объект» в viewmodelbase? - PullRequest
0 голосов
/ 28 октября 2019

Я только начал заниматься MVVM, потому что слышал о его преимуществах:

  1. Чистый код
  2. Код многократного использования
  3. Лучший код организован

Итак, начал делать обычный «Код позади», чтобы убедиться, что мой код работает, а затем применить MVVM для его очистки. так вот один из моих примеров «кода позади»:

private const int LED_PIN = 17, RELAY_PIN = 27;
private GpioPin LEDpin, RELAYpin;

    private bool InitGPIO(TextBlock txt)
    {
        var gpio = GpioController.GetDefault();

        // Show an error if there is no GPIO controller
        if (gpio == null)
        {
            txt.Text = "There is no GPIO controller on this device.";
            txt.Foreground = new SolidColorBrush(Colors.Red);
            return false;
        }

        txt.Text = "GPIO controller initialized correctly.";
        txt.Foreground = new SolidColorBrush(Colors.Green);

        LEDpin = gpio.OpenPin(LED_PIN);
        RELAYpin = gpio.OpenPin(RELAY_PIN);
        LEDpinValue = GpioPinValue.Low;
        RELAYpinValue = GpioPinValue.High;
        LEDpin.Write(LEDpinValue);
        RELAYpin.Write(RELAYpinValue);
        LEDpin.SetDriveMode(GpioPinDriveMode.Output);
        RELAYpin.SetDriveMode(GpioPinDriveMode.Output);
        return true;
    }

Чтобы использовать этот метод «InitGPIO», я должен предоставить:

  1. фиксированный «int» вывод.
  2. Типы GpioPin.
  3. Тип GpioPinValue.
  4. Текстовый блок для отображения того, что не так.

Я уже создал ViewModelBase и метод упрощения, чтобы получитьон читал:

public class ViewModelBase
{
    public InitGpioCommand InitGpiocommand { get; set; }
    public ViewModelBase() 
    {
        this.InitGpiocommand = new InitGpioCommand(this);
    }

    public bool InitGPIO(DigitalControl dc)
    {
        var gpio = GpioController.GetDefault();

        // Show an error if there is no GPIO controller
        if (gpio == null)
        {
            dc.Status.Text = "There is no GPIO controller on this device.";
            dc.Status.Foreground = new SolidColorBrush(Colors.Red);
            return false;
        }

        dc.Status.Text = "GPIO controller initialized correctly.";
        dc.Status.Foreground = new SolidColorBrush(Colors.Green);

        dc.DevicePin = gpio.OpenPin(dc.PinNumber);
        dc.PinValue = GpioPinValue.Low;
        dc.DevicePin.Write(dc.PinValue);
        dc.DevicePin.SetDriveMode(GpioPinDriveMode.Output);
        return true;
    }
}

все было обернуто в этой модели:

public class DigitalControl
{
    public TextBlock Status { get; set; }
    public GpioPin DevicePin  { get; set; }
    public GpioPinValue PinValue { get; set; }
    public int PinNumber { get; set; }
}

и моя текущая кнопка для запуска метода InitGPIO:

   <Button x:Name="FirstLightTest"
           Content="Test" 
           Command="{Binding InitGPIO,Source={StaticResource viewmodel}}">
   </Button>

OfКонечно, это не сработает.

Я понимаю, что должен:

  1. Передать "TextBlock" из xaml в параметр метода в ViewModelBase.
  2. Назначить GpioPin,GpioPinValue и PinNumber где-то в коде C #, а также передают их в метод внутри ViewModelBase.

Для того, чтобы заполнить все параметры в этом методе. Я действительно не знаю, плохой ли это дизайн MVVM или нет, но я думаю, что лучше всего использовать этот сложный шаблон, чтобы разбить его на мелкие проблемы, подобные этой, и посмотреть, насколько он ценен.

Ответы [ 2 ]

1 голос
/ 28 октября 2019

В коде есть некоторые ошибки. Прежде всего, Binding связан с InitGIPO, что является методом. Это не будет работать, поскольку Command может быть привязано только к свойству ICommand. В этом случае правильной целью будет InitGpiocommand. Я всегда рекомендую использовать существующую среду MVVM в качестве отправной точки, например, среду MVVM Light или MvvmCross. Они обеспечивают реализацию простого DelegateCommand, который может просто вызывать простой метод без параметров. Затем вы можете получить метод, похожий на этот:

private bool InitGPIO()
{
    ...
}

Теперь, где мы получаем экземпляр DigitalControl? Мы добавим в нашу модель представления свойство, которое будет представлять этот экземпляр:

public DigitalControl DigitalControl { get; } = new DigitalControl();

Как уже упоминалось @max, определенно не рекомендуется помещать элементы управления пользовательского интерфейса в любые свойства модели представления, поэтому давайте изменим определение DigitalControl к этому:

public class DigitalControl
{
    public string Status { get; set; }
    public GpioPin DevicePin  { get; set; }
    public GpioPinValue PinValue { get; set; }
    public int PinNumber { get; set; }
}

Свойство Status теперь может быть привязано к данным к TextBlock, например:

<TextBlock Text="{Binding DigitalControl.Status, Mode=TwoWay}" .../>

Один разпользователь изменяет TextBlock, изменение автоматически распространяется на свойство Status экземпляра модели представления *1027*.

Чтобы ссылаться на свойство DigitalControl в InitGIPO, вы можете просто ссылаться на него как на любоедругое свойство в представлении модели.

1 голос
/ 28 октября 2019

Для меня наличие компонента UI (TextBlock) внутри модели является нарушением MVVM-паттерна. Вместо этого свойства TextBlock должны быть связаны с моделью представления через механизм привязки и не назначаться напрямую. Подводя итог:

  1. Удалите ссылку TextBlock из модели
  2. Укажите свойства в модели представления, с которыми можно связать TextBlock (текст, цвет переднего плана илилогический флаг).
  3. Привязка к свойствам модели представления из xaml.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...