Как я могу протестировать ViewModel, который должен координировать создание и размещение UserControls? - PullRequest
1 голос
/ 01 марта 2020

Я работаю над демонстрационным проектом MVVM, в котором у меня есть главное окно WPF с ViewModel, которое должно координировать создание и размещение различных пользовательских элементов управления. Если ViewModel не должен иметь какой-либо части элементов WPF, я не уверен, как это сделать go. Я знаю, что это довольно широкий вопрос проектирования, но я новичок в WPF / TDD, и мне трудно найти четкий путь к тому, как создать и связать UserControl с ViewModel, не имея при этом каких-либо функций create и bind код в ViewModel.

Из того, что я прочитал, предоставление свойства UserControl в MainViewModel, которое привязывается к ContentControl, не является способом go. Как я могу абстрагироваться от создания и привязки UserControls в моей модели MainView, чтобы я мог проверить это?

Работает, но не тестируется:

<ContentControl Grid.Row="2" Content="{Binding UserControl}" />

public class MainWindowViewModel
{
    public void ShowHome()
    {
        SomeUserControl uc = new SomeUserControl();
        uc.DataContext = new SomeUserControlViewModel();
        UserControl = uc;
    }

    public void ShowKeypad()
    {
        SomeOtherUserControl uc = new SomeOtherUserControl();
        uc.DataContext = new SomeOtherUserControlViewModel();
        UserControl = uc;
    }

    public UserControl UserControl {get; private set;}
}



Ответы [ 3 ]

2 голосов
/ 02 марта 2020

просто используйте DataTemplate. Позвольте Wpf выбрать вид для вас.

<ContentControl Grid.Row="2" Content="{Binding UserControl}" />

public class MainWindowViewModel
{
  public void ShowHome()
  {
    MyViewmodelChoosedInMain  = new SomeViewModel();
  }

 public void ShowKeypad()
 {
    MyViewmodelChoosedInMain  = new SomeOtherViewModel();
 }

//better use an Interface instead of object type ;)
//you also need to implement and call INotifyPropertyChanged of course
 public object MyViewmodelChoosedInMain {get; private set;}
}

//in your ResourceDictionary create the DataTemplates
<DataTemplate DataType="{x:Type SomeViewModel}">
    <MySomeViewmodelView />
</DataTemplate>
<DataTemplate DataType="{x:Type SomeOtherViewModel}">
    <MySomeOtherViewmodelView />
</DataTemplate>
1 голос
/ 01 марта 2020

Есть пара вещей, которые вы можете сделать.

  1. Я создал много проектов, в которых представление при запуске создает элементы управления, в которых видимость установлена ​​на Скрытый. Затем виртуальная машина создает / имеет свойство State, которое определяет различные состояния приложения. При изменении этого свойства (через INotifyPropertyChanged) элементы управления на экране появляются или скрываются.

  2. Работая с # 1 или без него, можно создавать команды, которые представление может процесс , но который инициируется виртуальной машиной или где-либо еще. Следовательно, сохраняя разделение интересов.


# 1

Определить Enum

public enum OperationState
{
    Select = 1,
    Routine,
    Alignment,
    SerialNumber,
}

На ВМ определить состояние

private OperationState _State;

public OperationState State
{
    get => _State;
    set { _State = value; OnPropertyChanged(nameof(State)); }
}

Установите необходимое состояние, например, State = Select.

Иметь видимость элементов управления в зависимости от состояния

<Control:AlignmentProcessing 
            ProjectContainer="{Binding CurrentContainer, Mode=TwoWay}"
            Visibility="{Binding State, Converter={StaticResource VisibilityStateConverter},
                                        ConverterParameter=Alignment}"/>

Вышеуказанный элемент управления будет виден только во время Alignment state.

Код преобразователя

/// <summary>
/// Take the current state, passed in as value which is bound, and check it against
/// the parameter passed in. If the names match, the control should be visible,
/// if not equal, then the control (window really) should be collapsed.
/// </summary>
public class OperationStateToVisibility : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (value != null) &&
               (parameter != null) &&
               value.ToString().Equals(parameter.ToString(), StringComparison.OrdinalIgnoreCase)
            ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    => throw new NotImplementedException();

}

# 2 В противном случае выполните командную операцию на виртуальной машине, например:

public ICommand ShowControl1 { get; set; }

Затем в представлении подписаться на команду (при условии, что VM содержит текущую виртуальную машину):

    VM.ShowControl1 = new Commanding((o) =>
    {
        SomeUserControl uc = new SomeUserControl();
        uc.DataContext = new SomeUserControlViewModel();
        UserControl = uc;
    }

Затем, когда команда выполняется (из виртуальной машины), представление выполняет свою работу.

 ShowControl1.Execute(null);

Я предоставляю командный пример в своем блоге Xaml: MVVM Пример для более простой привязки

0 голосов
/ 01 марта 2020

Модель представления должна , а не иметь какие-либо элементы управления с шаблоном MVVM. Модель представления - это просто состояние отображаемых данных.

Например:

  • Записи для отображения
  • Заголовок
  • Изображение
  • Можно удалить
  • Можно редактировать

В WPF элементы управления могут связываться с этими свойствами для отображения.

View-модели - это агенты вида c (им все равно, какой вид потребляет его). И поэтому в них не будет реальной ссылки на элементы управления пользовательским интерфейсом.

Чтобы проверить действительный пользовательский интерфейс, вы можете написать «кодированный тест пользовательского интерфейса». В работающем веб-приложении есть платформа Selenium, которая позволяет вам писать модульные тесты для взаимодействия с компонентами пользовательского интерфейса в браузере.

Я почти уверен, что для тестирования WPF UI существует аналогичная среда.

Редактировать: Существует платформа под названием Appium, которая позволяет вам писать интеграционные тесты между вашим пользовательским интерфейсом и имеющейся у вас базовой установкой MVVM.

http://appium.io/docs/en/drivers/windows/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...