Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何测试需要协调用户控件的创建和宿主的ViewModel?_C#_Wpf_Mvvm - Fatal编程技术网

C# 如何测试需要协调用户控件的创建和宿主的ViewModel?

C# 如何测试需要协调用户控件的创建和宿主的ViewModel?,c#,wpf,mvvm,C#,Wpf,Mvvm,我正在进行一个演示MVVM项目,其中我有一个WPF主窗口和一个ViewModel,需要协调不同用户控件的创建和托管。如果ViewModel不应该包含WPF元素的任何部分,那么我不知道该怎么做。我知道这是一个相当广泛的设计问题,但我是WPF/TDD新手,我很难看到一条清晰的路径,即如何创建用户控件并将其绑定到ViewModel,而不必在ViewModel中使用一些创建和绑定代码 从我所读到的内容来看,在MainViewModel中公开绑定到ContentControl的UserControl属性不

我正在进行一个演示MVVM项目,其中我有一个WPF主窗口和一个ViewModel,需要协调不同用户控件的创建和托管。如果ViewModel不应该包含WPF元素的任何部分,那么我不知道该怎么做。我知道这是一个相当广泛的设计问题,但我是WPF/TDD新手,我很难看到一条清晰的路径,即如何创建用户控件并将其绑定到ViewModel,而不必在ViewModel中使用一些创建和绑定代码

从我所读到的内容来看,在MainViewModel中公开绑定到ContentControl的UserControl属性不是一个好办法。如何在MainView模型中抽象出UserControls的创建和绑定,以便对其进行测试

工作但不可测试:

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



视图模型中不应包含任何具有MVVM模式的控件。视图模型只是要显示的数据的状态

例如:

要显示的记录 标题 形象 可以删除 可以编辑 在WPF中,控件可以绑定到这些属性以进行显示

视图模型是视图不可知的,它们不关心哪个视图在使用它。因此,它们中不会有对UI控件的实际引用

要测试实际的UI,可以编写编码的UI测试。在web应用程序中,有一个Selenium框架,允许您编写与浏览器中的UI组件交互的单元测试

我敢肯定,WPF UI测试也有类似的框架

编辑:有一个名为Appium的框架,允许您编写UI和底层MVVM设置之间的集成测试

视图模型中不应包含任何具有MVVM模式的控件。视图模型只是要显示的数据的状态

例如:

要显示的记录 标题 形象 可以删除 可以编辑 在WPF中,控件可以绑定到这些属性以进行显示

视图模型是视图不可知的,它们不关心哪个视图在使用它。因此,它们中不会有对UI控件的实际引用

要测试实际的UI,可以编写编码的UI测试。在web应用程序中,有一个Selenium框架,允许您编写与浏览器中的UI组件交互的单元测试

我敢肯定,WPF UI测试也有类似的框架

编辑:有一个名为Appium的框架,允许您编写UI和底层MVVM设置之间的集成测试


你可以做几件事

我创建了许多项目,其中启动时的视图创建了可见性设置为隐藏的控件。然后VM创建/拥有一个状态属性,该属性定义应用程序的不同状态。当该属性通过INotifyPropertyChanged更改时,屏幕上的控件会显示或隐藏自己

使用1或不使用1,可以创建视图可以处理但由VM或其他地方启动的命令。因此,保持关注点的分离

一,

定义枚举

关于VM定义状态

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}"/>
2否则,在VM上执行命令操作,例如:

public ICommand ShowControl1 { get; set; }
然后在视图上订阅命令,假设VM持有当前VM:

    VM.ShowControl1 = new Commanding((o) =>
    {
        SomeUserControl uc = new SomeUserControl();
        uc.DataContext = new SomeUserControlViewModel();
        UserControl = uc;
    }
然后,当从VM执行命令时,视图执行其工作

 ShowControl1.Execute(null);

我在我的博客上提供了一个很好的例子,你可以做一些事情

我创建了许多项目,其中启动时的视图创建了可见性设置为隐藏的控件。然后VM创建/拥有一个状态属性,该属性定义应用程序的不同状态。当该属性通过INotifyPropertyChanged更改时,屏幕上的控件会显示或隐藏自己

使用1或不使用1,可以创建视图可以处理但由VM或其他地方启动的命令。因此,保持关注点的分离

一,

定义枚举

关于VM定义状态

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}"/>
2否则,在VM上执行命令操作,例如:

public ICommand ShowControl1 { get; set; }
然后在视图上订阅命令,假设VM持有当前VM:

    VM.ShowControl1 = new Commanding((o) =>
    {
        SomeUserControl uc = new SomeUserControl();
        uc.DataContext = new SomeUserControlViewModel();
        UserControl = uc;
    }
然后,当从VM执行命令时,视图执行其工作

 ShowControl1.Execute(null);

我在我的博客上提供了一个命令式的例子,只需使用数据模板即可。让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>

只需使用数据模板。让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>

人们将MVVM视为一种宗教,而不是教条。它只是将GUI、业务处理和数据库之间的关注点分离开来。它过去被称为三层方法。因此,您希望您需要做什么才能使其工作,但要将主要组件保持在其层内;仅此而已。这是我的观点,我可能错了
人们把MVVM当作一种宗教,而不是教条。它只是将GUI、业务处理和数据库之间的关注点分离开来。它过去被称为三层方法。因此,您希望您需要做什么才能使其工作,但要将主要组件保持在其层内;仅此而已。这是我的观点,我可能错了。我已经能够按照您的指导原则测试所有的UserControl视图模型。我遇到的一个问题是MainView模型,我不知道该方法,因为它非常清楚需要创建和协调的视图。我以前使用过Selenium,但在本例中,我没有进行集成测试。我已经能够按照您的指导原则测试所有UserControl视图模型。我遇到的一个问题是MainView模型,我不知道该方法,因为它非常清楚需要创建和协调的视图。我以前使用过Selenium,但在本例中我没有进行集成测试。对于初学者来说,提及模板也可以位于页面资源或父控件的资源部分可能会有所帮助。最好的位置是app.xaml ResourceDictionary。我更喜欢这样:-对于初学者,提及模板也可以位于页面资源或父控件的资源部分可能会有所帮助。最好的位置是app.xaml ResourceDictionary。我更喜欢这样:-