C# 如何通过主视图模型将UserControl内容更改为另一个UserControl。如何在内容之间导航
我有一个主窗口,其中有一个侧栏用于导航,还有一个用户控件,其中显示了3个视图(默认值、视图1、视图2)。在主视图模型(称为AppVM)中,我正在将contentcontrol初始化为默认视图,该视图有一个按钮可前进到view1(导航侧栏除外)。我在AppVM中有命令可以切换到三个视图中的任意一个。View1还有另一个按钮,应该移动到view2(使用主视图模型中的命令)。但是,每当我按下view1中的按钮(移动到view2)时,显示不会改变。奇怪的是,在调试时,按view1中的按钮时,内容控件绑定到的变量被设置为默认视图,而不是当前视图(即view1) 我认为,按照我设置命令的方式,它会创建内容控件绑定变量的新实例,但我不知道如何使它使用相同的实例,而不一次又一次地打开新实例 主视图模型(AppVM) 视图1虚拟机C# 如何通过主视图模型将UserControl内容更改为另一个UserControl。如何在内容之间导航,c#,wpf,xaml,user-controls,C#,Wpf,Xaml,User Controls,我有一个主窗口,其中有一个侧栏用于导航,还有一个用户控件,其中显示了3个视图(默认值、视图1、视图2)。在主视图模型(称为AppVM)中,我正在将contentcontrol初始化为默认视图,该视图有一个按钮可前进到view1(导航侧栏除外)。我在AppVM中有命令可以切换到三个视图中的任意一个。View1还有另一个按钮,应该移动到view2(使用主视图模型中的命令)。但是,每当我按下view1中的按钮(移动到view2)时,显示不会改变。奇怪的是,在调试时,按view1中的按钮时,内容控件绑定
public class View1VM : ObservableObject {
public InfoClass View1InfoClass { get; set; }
public View1VM() { View1InfoClass = new InfoClass //Apparently I need to instantiate and initialize this to activate binding {
FirstName = "Abbas",
//FirstName = passedInforClass,
LastName = "Syed",
Number = 12
};
} }
view1.xaml中的命令
<UserControl.Resources>
<vm:AppVM x:Name="AppVMinView1" x:Key="AppVMinView1"></vm:AppVM>
</UserControl.Resources>
<UserControl.DataContext>
<vm:View1VM></vm:View1VM>
</UserControl.DataContext>
<Grid Background="Aqua">
<StackPanel Margin="100">
<TextBlock Text="First Name"/>
<TextBox x:Name="firstNameTextBoxView1" Text="{Binding View1InfoClass.FirstName, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<TextBlock Text="Last Name"/>
<TextBox x:Name="lastNameTextBoxView1" Text="{Binding View1InfoClass.LastName, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<TextBlock Text="Random Useless Number" ></TextBlock>
<TextBox x:Name="randomUselessNumberView1" Text="{Binding View1InfoClass.Number, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<TextBlock Text="First Name Entered"></TextBlock>
<TextBlock Text="{Binding View1InfoClass.FirstName}"></TextBlock>
<TextBlock Text="Last Name Entered" ></TextBlock>
<TextBlock Text="{Binding View1InfoClass.LastName}"></TextBlock>
<TextBlock Text="Random Useless Number Entered"></TextBlock>
<TextBlock Text="{Binding View1InfoClass.Number}"></TextBlock>
<Button DataContext="{DynamicResource AppVMinView1}" Content="Go to view2" Height="20" Width="70" Command="{Binding View2ButtonCommand}" />
</StackPanel>
</Grid>
根据我所读到的(这里和互联网上),我需要将视图设置为单例视图,我尝试的方法是使用私有setter将view2的静态属性声明为一个新的view2,但这并没有阻止它。如果能在这方面得到任何帮助,我将不胜感激
我还应该补充一点,即使当view1中要更改为view2的按钮不起作用时,侧导航栏按钮也可以正常工作 看起来您正在创建多个
AppVm
实例View1
中的按钮和导航栏的按钮显然没有绑定到同一个AppVm
这同样适用于
CurrentView
属性:您的内容主机绑定到不同的实例,即不同于您在View1
中修改的CurrentView
的属性值引用。因此,从View1
内部更改CurrentView
不会对内容主机-->视图产生任何影响。确保始终在同一上下文中引用同一(共享)实例 根据用户界面的结构,有多种方法可以实现这一点。创建视图模型类的单例是迄今为止最糟糕的选择。单身人士应该也可以永远避免 最简单的解决方案是在应用程序xaml
ResourceDictionary
中将视图模型声明为资源:
App.xaml通过
StaticResource
markup extension资源字典查找,此文件中定义的资源在任何XAML上下文中都是全局可用的
<Application>
<Application.Resources>
<AppVM x:Key="AppVMinView1" />
</Application.Resources>
</Application>
View1.xaml
<!-- DataContext is inherited from the surrounding DataTemplate and is the corresponding page view model -->
<UserControl>
<StackPanel>
<TextBox Text="{Binding View1InfoClass.FirstName}" />
<!--
Bind to the command of the same view model instance,
which is the DataContext of the content host
-->
<Button Content="Show View2"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=MainWindow}, Path=DataContext.View2ButtonCommand}" />
</StackPanel>
</UserControl>
<Window>
<Window.DataContext>
<AppVM />
</Window.DataContext>
<Window.Resources>
<!-- Define the views as implicit (keyless) DataTemplate -->
<DataTemplate DataType="{x:Type DefaultVM}">
<DefaultView />
</DataTemplate>
<DataTemplate DataType="{x:Type View1VM}">
<View1 />
</DataTemplate>
<DataTemplate DataType="{x:Type View2VM}">
<View2 />
</DataTemplate>
</Window.Resources>
<!--
Host of the pages.
The implicit DataTemplates will apply automatically
and show the control that maps to the current CurrentView view model
-->
<ContentPresenter Content="{Binding CurrentView}" />
</Window>
main window.xaml
<!-- DataContext is inherited from the surrounding DataTemplate and is the corresponding page view model -->
<UserControl>
<StackPanel>
<TextBox Text="{Binding View1InfoClass.FirstName}" />
<!--
Bind to the command of the same view model instance,
which is the DataContext of the content host
-->
<Button Content="Show View2"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=MainWindow}, Path=DataContext.View2ButtonCommand}" />
</StackPanel>
</UserControl>
<Window>
<Window.DataContext>
<AppVM />
</Window.DataContext>
<Window.Resources>
<!-- Define the views as implicit (keyless) DataTemplate -->
<DataTemplate DataType="{x:Type DefaultVM}">
<DefaultView />
</DataTemplate>
<DataTemplate DataType="{x:Type View1VM}">
<View1 />
</DataTemplate>
<DataTemplate DataType="{x:Type View2VM}">
<View2 />
</DataTemplate>
</Window.Resources>
<!--
Host of the pages.
The implicit DataTemplates will apply automatically
and show the control that maps to the current CurrentView view model
-->
<ContentPresenter Content="{Binding CurrentView}" />
</Window>
你的问题格式很奇怪。有些代码甚至不显示。代码应仅格式化为代码而不是块引号。您的按钮设置了工作DataContext
。DataContext
必须是AppVM
,否则命令
绑定无法解析。将视图设置为单例是没有用的。你好,BionicCode。感谢您的回复,并指出错误的格式(很抱歉!)我将它绑定到AppVM,但在调试时,单击View1中的按钮导航到View2时,我在AppVM中到达了断点,但CurrentView变量设置为DefaultVM(但它应该是View1[它的最后一个值])。看起来您正在创建多个AppVm实例。确保始终使用相同的实例。您正在修改的实例不是触发新视图的实例。您好BionicCode。谢谢你回复我。事实上,这是我感到困惑的部分。我了解到可以声明主视图模型(AppVM)的静态属性以使用同一实例。但是,由于我有非静态成员(命令),所以不能有静态构造函数。还有别的办法吗?我很抱歉,如果我听起来很愚蠢,这是我的第一个项目。谢谢你花时间来做这件事!你好,生物代码。非常感谢您的详细回答!
<Window>
<Window.DataContext>
<AppVM />
</Window.DataContext>
<Window.Resources>
<!-- Define the views as implicit (keyless) DataTemplate -->
<DataTemplate DataType="{x:Type DefaultVM}">
<DefaultView />
</DataTemplate>
<DataTemplate DataType="{x:Type View1VM}">
<View1 />
</DataTemplate>
<DataTemplate DataType="{x:Type View2VM}">
<View2 />
</DataTemplate>
</Window.Resources>
<!--
Host of the pages.
The implicit DataTemplates will apply automatically
and show the control that maps to the current CurrentView view model
-->
<ContentPresenter Content="{Binding CurrentView}" />
</Window>