wpf 如何在我的 MVVM 项目中的用户控件之间切换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32230086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I switch between user controls in my MVVM project
提问by BeeLabeille
Edit: Although this question has been flagged up by @AbinMathew as a possible duplicate of this, the solution provided to that question didn't explain very well how to relay the command logic. I was able to resolve this with the help of John Smith's article as mentioned in my answer.
编辑:尽管@AbinMathew 已将此问题标记为可能与此重复,但提供给该问题的解决方案并没有很好地解释如何中继命令逻辑。正如我的回答中提到的那样,我能够在约翰史密斯文章的帮助下解决这个问题。
I've got this test project which I'm running in order to get my head around MVVM. What I'm trying to achieve: MainWindow has a back button and a ContentControl. On Window_loaded I want to display MainGadget in the ContentControl. When I click MyBtn in MainGadget, I want to then display MyGadget in the ContentControl.
我有一个我正在运行的测试项目,以便让我了解 MVVM。我想要实现的目标:MainWindow 有一个后退按钮和一个 ContentControl。在 Window_loaded 我想在 ContentControl 中显示 MainGadget。当我在 MainGadget 中单击 MyBtn 时,我想在 ContentControl 中显示 MyGadget。
ViewModelBase is a class which is used by MainGadgetVM, MainWindowVM and MyGadgetVM. It implements the INotifyPropertyChanged interface. RelayCommand implements the ICommand interface so I want to use it for executing MyBtn_Click and displaying other UserControls.
ViewModelBase 是 MainGadgetVM、MainWindowVM 和 MyGadgetVM 使用的类。它实现了 INotifyPropertyChanged 接口。RelayCommand 实现了 ICommand 接口,所以我想用它来执行 MyBtn_Click 并显示其他 UserControl。
At the moment, when I run the program only the 'Back' button is displayed. I can't seem to figure out how to display the other UserControls. Any help will be much appreciated.
目前,当我运行程序时,只显示“返回”按钮。我似乎无法弄清楚如何显示其他用户控件。任何帮助都感激不尽。
DataTemplates.xaml
数据模板.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ExampleContentCtrl.VMs"
xmlns:view="clr-namespace:ExampleContentCtrl.Panels">
<DataTemplate DataType="{x:Type vm:MainGadgetVM}">
<view:MainGadget/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:MyGadgetVM}">
<view:MyGadget/>
</DataTemplate>
</ResourceDictionary>
MainWindow.xaml
主窗口.xaml
<Window x:Class="ExampleContentCtrl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="375" Width="300" Loaded="Window_Loaded">
<Window.Resources>
<ResourceDictionary Source="DataTemplates.xaml"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="8*"/>
</Grid.RowDefinitions>
<Button x:Name="BckSpace" Content="Back" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0"/>
<ContentControl Grid.Row="1"/>
</Grid>
</Window>
MainGadget.xaml
主小工具.xaml
<UserControl x:Class="ExampleContentCtrl.Panels.MainGadget"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button x:Name="MyBtn" Content="My Gadget" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Row="1" Command="{Binding MyBtn_Click}"/>
</Grid>
</UserControl>
MainWindow.xaml.cs
主窗口.xaml.cs
namespace ExampleContentCtrl
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Load MainGadgetVM via MainWindowVM.Initialize()
}
}
}
MainWindowVM.cs
主窗口虚拟机.cs
namespace ExampleContentCtrl.VMs
{
public class MainWindowVM : ViewModelBase
{
private RelayCommand _ShowWorkSpace;
private static MainWindowVM _Instance;
public static MainWindowVM Instance { get { return _Instance; } }
public MainWindowVM()
{
MainWindowVM._Instance = this;
}
public RelayCommand ShowWorkSpace
{
get
{
if (_ShowWorkSpace == null)
_ShowWorkSpace = new RelayCommand(param => { });
return _ShowWorkSpace;
}
}
public void Initialize()
{
//this.ShowWorkSpace.Execute("ExampleContentCtrl.VMs.MainGadgetVM");
}
}
}
回答by Onur
Add a binding to your content control and change the bound value to the view model you want to show.
向内容控件添加绑定并将绑定值更改为要显示的视图模型。
<Window x:Class="ExampleContentCtrl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="375" Width="300" Loaded="Window_Loaded">
<Window.Resources>
<ResourceDictionary Source="DataTemplates.xaml"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="8*"/>
</Grid.RowDefinitions>
<Button x:Name="BckSpace" Content="Back" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0"/>
<ContentControl Grid.Row="1" Content={Binding Path=MyContent}/>
</Grid>
</Window>
public class MainWindowVM
{
//...
public MainViewModel
{
MyContent = new TheViewModelThatShouldBeShownAtStart();
}
public object MyContent
{
get; private set; // add Notification!
}
void FunctionCalledWhenButtonIsPressed()
{
if (...) // add your logic here
MyContent = new VM1();
else
MyContent = new VM2();
}
}
回答by Mahmoud salah eldien saber
Grid.Children.Clear();
Grid.Children.Add(new NextUserControl());
回答by d.moncada
You can use a style inside your content control that will switch its content based on a common bound property within your main ViewModel.
您可以在内容控件中使用样式,该样式将根据主 ViewModel 中的公共绑定属性切换其内容。
Something like:
就像是:
<Window x:Class="ExampleContentCtrl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="375" Width="300" Loaded="Window_Loaded">
<Window.Resources>
<ResourceDictionary Source="DataTemplates.xaml"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="8*"/>
</Grid.RowDefinitions>
<Button x:Name="BckSpace" Content="Back" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0"/>
<ContentControl Grid.Row="1">
<ContentControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding UserControlToShow}" Value="MainGadget">
<Setter Property="ContentControl.Content" Value="{StaticResource MainGadget}"/>
</DataTrigger>
<DataTrigger Biniding="{Binding UserControlToShow}" Value="MyGadget">
<Setter Property="ContentControl.Content" Value="{StaticResource MyGadget}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
</Window>
Then, update your ResourceDictionary so that the DateTemplateshave keys:
然后,更新您的 ResourceDictionary 以便DateTemplates有键:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ExampleContentCtrl.VMs"
xmlns:view="clr-namespace:ExampleContentCtrl.Panels">
<DataTemplate DataType="{x:Type vm:MainGadgetVM}" x:Key="MainGadget">
<view:MainGadget/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:MyGadgetVM}" x:Key="MyGadget">
<view:MyGadget/>
</DataTemplate>
</ResourceDictionary>
Now, add the property that is used as the trigger to switch content:
现在,添加用作切换内容的触发器的属性:
public class MainWindowVM : ViewModelBase
{
private RelayCommand _ShowWorkSpace;
private static MainWindowVM _Instance;
public static MainWindowVM Instance { get { return _Instance; } }
private string _userControlToShow;
public string UserControlToShow
{
get { return _userControlToShow; }
set
{
_userControlToShow = value;
RaisePropertyChanged("UserControlToShow");
}
}
public MainWindowVM()
{
MainWindowVM._Instance = this;
}
public RelayCommand ShowWorkSpace
{
get
{
if (_ShowWorkSpace == null)
_ShowWorkSpace = new RelayCommand(param => { });
return _ShowWorkSpace;
}
}
}


