C# 一个视图模型中的两个视图(WPF/MVVM)
问题:将一个viewModel与两个不同的视图一起使用 我有一个C# 一个视图模型中的两个视图(WPF/MVVM),c#,wpf,mvvm,C#,Wpf,Mvvm,问题:将一个viewModel与两个不同的视图一起使用 我有一个窗口,其中有一个控件ContentControl,该控件绑定到DataContext中的一个属性,名为objectmaincontent{get;set;}。基于navigationTypeenum属性,我将其他ViewModels分配给它,以显示正确的UserControl 我需要将两个视图合并到一个视图模型中,因为我正在将一个视图模型分配给前面提到的ContentControl,所以TemplateSelector无法识别哪个视
窗口
,其中有一个控件ContentControl
,该控件绑定到DataContext
中的一个属性,名为objectmaincontent{get;set;}
。基于navigationTypeenum
属性,我将其他ViewModels分配给它,以显示正确的UserControl
我需要将两个视图合并到一个视图模型中,因为我正在将一个视图模型分配给前面提到的ContentControl
,所以TemplateSelector
无法识别哪个视图是正确的视图,因为两者共享同一个视图模型
如果我将视图而不是ViewModel指定给ContentControl
,则会显示正确的视图,但是没有任何命令起作用
有什么帮助吗?提前谢谢。
解决方案:基于@mm8答案和: ManagePatientViewModel.cs
public class ManagePatientViewModel : ViewModelBase
{
public ManagePatientViewModel (MainWindowViewModel inMainVM) : base(inMainVM) {}
}
public ViewState State {get;set;}
public ManagePatientViewModel VM {get;set;}
private void ChangeView(ViewState inState)
{
State = inState;
// This is need to force the update of Content.
var copy = VM;
MainContent = null;
MainContent = copy;
}
public void NavigateTo (NavigationType inNavigation)
{
switch (inNavigationType)
{
case NavigationType.CREATE_PATIENT:
ChangeView(ViewState.CREATE);
break;
case NavigationType.SEARCH_PATIENT:
ChangeView(ViewState.SEARCH);
break;
default:
throw new ArgumentOutOfRangeException(nameof(inNavigationType), inNavigationType, null);
}
}
ViewHelper.cs
public enum ViewState
{
SEARCH,
CREATE,
}
MainWindowViewModel.cs
public class ManagePatientViewModel : ViewModelBase
{
public ManagePatientViewModel (MainWindowViewModel inMainVM) : base(inMainVM) {}
}
public ViewState State {get;set;}
public ManagePatientViewModel VM {get;set;}
private void ChangeView(ViewState inState)
{
State = inState;
// This is need to force the update of Content.
var copy = VM;
MainContent = null;
MainContent = copy;
}
public void NavigateTo (NavigationType inNavigation)
{
switch (inNavigationType)
{
case NavigationType.CREATE_PATIENT:
ChangeView(ViewState.CREATE);
break;
case NavigationType.SEARCH_PATIENT:
ChangeView(ViewState.SEARCH);
break;
default:
throw new ArgumentOutOfRangeException(nameof(inNavigationType), inNavigationType, null);
}
}
MainWindow.xaml
<DataTemplate x:Key="CreateTemplate">
<views:CreateView />
</DataTemplate>
<DataTemplate x:Key="SearchTemplate">
<views:SearchView/>
</DataTemplate>
<TemplateSelector x:Key="ViewSelector"
SearchViewTemplate="{StaticResource SearchTemplate}"
CreateViewTemplate="{StaticResource CreateTemplate}"/>
<ContentControl
Grid.Row="1"
Content="{Binding MainContent}"
ContentTemplateSelector="{StaticResource ViewSelector}" />
当有两种视图类型映射到单个视图模型类型时,
TemplateSelector
如何知道要使用哪个模板?恐怕这毫无意义
您应该使用两种不同的类型。您可以在一个公共基类中实现该逻辑,然后定义两种标记类型,这两种类型仅从该实现派生,不添加任何功能:
public class ManagePatientViewModel { */put all your code in this one*/ }
//marker types:
public class SearchPatientViewModel { }
public class CreatePatientViewModel { }
此外,如果从模板中删除x:Key
属性,则实际上不需要模板选择器:
<DataTemplate DataType="{x:Type viewModels:SearchPatientViewModel}">
<views:SearchPatientView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:CreatePatientViewModel}">
<views:CreatePatientView />
</DataTemplate>
...
<ContentControl
Grid.Row="1"
Content="{Binding MainContent}" />
...
当有两个视图类型映射到一个视图模型类型时,TemplateSelector
如何知道要使用哪个模板?恐怕这毫无意义
您应该使用两种不同的类型。您可以在一个公共基类中实现该逻辑,然后定义两种标记类型,这两种类型仅从该实现派生,不添加任何功能:
public class ManagePatientViewModel { */put all your code in this one*/ }
//marker types:
public class SearchPatientViewModel { }
public class CreatePatientViewModel { }
此外,如果从模板中删除x:Key
属性,则实际上不需要模板选择器:
<DataTemplate DataType="{x:Type viewModels:SearchPatientViewModel}">
<views:SearchPatientView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:CreatePatientViewModel}">
<views:CreatePatientView />
</DataTemplate>
...
<ContentControl
Grid.Row="1"
Content="{Binding MainContent}" />
...
可能需要切换视图并保留单视图模型。
数据模板只是实例化视图的一种方法。
您可以将contentcontrol的datacontext设置为viewmodel的实例,并将视图切换为内容。因为视图是视图的责任,所以这些任务可以完全在视图中完成,而不会“破坏”mvvm。
这里有一个非常快速和肮脏的方法来说明我的意思。
我构建了两个用户控件,UC1和UC2。这些对应于您的各种患者视图。
以下是其中一个的标记:
<StackPanel>
<TextBlock Text="User Control ONE"/>
<TextBlock Text="{Binding HelloString}"/>
</StackPanel>
我的主窗口标记:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="UC1" Click="UC1_Click"/>
<Button Content="UC2" Click="UC2_Click"/>
</StackPanel>
<ContentControl Name="parent"
Grid.Column="1"
>
<ContentControl.DataContext>
<local:OneViewModel/>
</ContentControl.DataContext>
</ContentControl>
</Grid>
oneviewmodel的单个实例将被保留,并且显示的视图将被关闭。hellostring绑定并在两者中显示ok
在您的应用程序中,您需要一种更复杂的方法来设置datacontext,但此示例仅用于向您展示另一种方法的概念证明
以下是工作示例:
可能需要切换视图并保留单视图模型。 数据模板只是实例化视图的一种方法。 您可以将contentcontrol的datacontext设置为viewmodel的实例,并将视图切换为内容。因为视图是视图的责任,所以这些任务可以完全在视图中完成,而不会“破坏”mvvm。 这里有一个非常快速和肮脏的方法来说明我的意思。 我构建了两个用户控件,UC1和UC2。这些对应于您的各种患者视图。 以下是其中一个的标记:
<StackPanel>
<TextBlock Text="User Control ONE"/>
<TextBlock Text="{Binding HelloString}"/>
</StackPanel>
我的主窗口标记:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="UC1" Click="UC1_Click"/>
<Button Content="UC2" Click="UC2_Click"/>
</StackPanel>
<ContentControl Name="parent"
Grid.Column="1"
>
<ContentControl.DataContext>
<local:OneViewModel/>
</ContentControl.DataContext>
</ContentControl>
</Grid>
oneviewmodel的单个实例将被保留,并且显示的视图将被关闭。hellostring绑定并在两者中显示ok
在您的应用程序中,您需要一种更复杂的方法来设置datacontext,但此示例仅用于向您展示另一种方法的概念证明
以下是工作示例:
当有两个视图模型类型映射到一个视图类型时,TemplateSelector如何知道要使用哪个模板?这毫无意义。你应该使用两种不同的类型。谢谢你的回答@mm8,这就是我提问的原因,我不知道如何继续,或者我应该改变什么。你能告诉我正确的方向吗?我发布了一个答案。当有两个视图模型类型映射到一个视图类型时,TemplateSelector怎么知道要使用哪个模板?这毫无意义。你应该使用两种不同的类型。谢谢你的回答@mm8,这就是我提问的原因,我不知道如何继续,或者我应该做些什么。你能告诉我正确的方向吗?我发布了一个答案。我可能解释错了,我需要的是一个视图模型的两个不同视图,不是将两个视图模型放在一个视图中。我已经测试过了,我也有同样的问题,命令不起作用。问题是我已经有了两个不同的ViewModel,这就是为什么我一开始没有理解你的观点。一个是搜索,另一个是创建。我已经将它们合并到
ManagePatientViewModel
中,我应该对这两个视图都使用它。基本上,我认为TemplateSelector
可以一次选择哪个视图是正确的。基本上,我必须简化我们所有的视图和ViewsModel,使用一个视图模型(ManagePatientViewModel)创建两个视图(CreateView和SearchView)是有意义的。我想发布每个视图的代码,但是extense和Stack抱怨“代码太多”。我认为拥有两个具有相同ViewModel的视图是很容易的,我会忘记这一点。我已经更新了我的问题,我也应用了您的解决方案,但它不起作用,视图更改为正确的视图,但ViewModel中绑定的命令没有被调用。对于专家来说这可能很容易,但我只是WPF的新手。问题是TemplateSelector.SelectTemplate.Item是