C# MVVM Light-用户控件作为视图
我决定使用MVVM Light库来帮助设计UI。经过大量的研究和反复试验,我还没有找到我正在寻找的答案。我已经在谷歌上搜索并阅读了我能找到的每个StackOverflow问题,然而,我的问题似乎是独一无二的 我希望设计一个只有一个窗口的UI,并用不同的视图/用户控件填充它。我不希望用户控件之间共享导航栏,也不希望弹出多个窗口。每个视图/用户控件都应绑定到自己的ViewModel,而MainWindow将绑定到MainViewModel 示例场景-具有3个用户控件的主窗口C# MVVM Light-用户控件作为视图,c#,xaml,mvvm,user-controls,mvvm-light,C#,Xaml,Mvvm,User Controls,Mvvm Light,我决定使用MVVM Light库来帮助设计UI。经过大量的研究和反复试验,我还没有找到我正在寻找的答案。我已经在谷歌上搜索并阅读了我能找到的每个StackOverflow问题,然而,我的问题似乎是独一无二的 我希望设计一个只有一个窗口的UI,并用不同的视图/用户控件填充它。我不希望用户控件之间共享导航栏,也不希望弹出多个窗口。每个视图/用户控件都应绑定到自己的ViewModel,而MainWindow将绑定到MainViewModel 示例场景-具有3个用户控件的主窗口 1. MainWindo
1. MainWindow populates with first UserControl which has a listbox and 3 buttons, the first button is enabled.
2. User clicks the first button.
3. MainWindow populates with second UserControl.
或者,另外
2. User selects choice from a listbox, button two and three become available.
3. User clicks second/third button.
4. MainWindow populates with second/third UserControl.
等等等等
也许我的方法不现实,但我觉得这是可能的。我不明白如何在概念上使所有这些工作都有效。我的愿望不可能是独一无二的。如果您觉得这是重复的问题,请重定向。干杯
为了让事情更容易理解,我在下面加入了一些类。首先,我的App.xaml
<Application x:Class="Bobcat_BETA.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:Bobcat_BETA.UserControls"
xmlns:vm="clr-namespace:Bobcat_BETA.ViewModels"
StartupUri="MainWindow.xaml"
mc:Ignorable="d">
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
<DataTemplate DataType="{x:Type vm:SavedScenariosViewModel}">
<views:SavedScenariosUserControl />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ScenarioEditorViewModel}">
<views:ScenarioEditorUserControl />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SimulatorViewModel}">
<views:SimulatorUserControl />
</DataTemplate>
</Application.Resources>
</Application>
MainViewModel.cs
namespace Bobcat_BETA.ViewModels
{
public class MainViewModel : ViewModelBase
{
private ViewModelBase _currentViewModel;
readonly static SavedScenariosViewModel _savedScenarioViewModel = new SavedScenariosViewModel();
readonly static ScenarioEditorViewModel _scenarioEditorViewModel = new ScenarioEditorViewModel();
readonly static SimulatorViewModel _simulatorViewModel = new SimulatorViewModel();
public ViewModelBase CurrentViewModel
{
get
{
return _currentViewModel;
}
set
{
if (_currentViewModel == value)
return;
_currentViewModel = value;
RaisePropertyChanged("CurrentViewModel");
}
}
public MainViewModel()
{
CurrentViewModel = MainViewModel._savedScenarioViewModel;
SavedScenarioViewCommand = new RelayCommand(() => ExecuteSavedScenarioViewCommand());
ScenarioEditorViewCommand = new RelayCommand(() => ExecuteScenarioEidtorViewCommand());
SimulatorViewCommand = new RelayCommand(() => ExecuteSimulatorViewCommand());
}
public ICommand SavedScenarioViewCommand { get; private set; }
public ICommand ScenarioEditorViewCommand { get; private set; }
public ICommand SimulatorViewCommand { get; private set; }
private void ExecuteSavedScenarioViewCommand()
{
CurrentViewModel = MainViewModel._savedScenarioViewModel;
}
private void ExecuteScenarioEidtorViewCommand()
{
CurrentViewModel = MainViewModel._scenarioEditorViewModel;
}
private void ExecuteSimulatorViewCommand()
{
CurrentViewModel = MainViewModel._simulatorViewModel;
}
}
}
namespace Bobcat_BETA.ViewModels
{
public class SavedScenariosViewModel : ViewModelBase
{
public SavedScenariosViewModel()
{
}
ObservableCollection<ScenarioModel> _scenarioModels = new ObservableCollection<ScenarioModel>()
{
new ScenarioModel() {Name = "Scenario 0", ID = 000, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 1", ID = 001, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 2", ID = 002, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 3", ID = 003, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 4", ID = 004, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 5", ID = 005, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 6", ID = 006, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 7", ID = 007, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 8", ID = 008, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 9", ID = 009, Desc = "This will describe the Scenario Model."}
};
public ObservableCollection<ScenarioModel> ScenarioModels
{
get { return _scenarioModels; }
}
}
}
SavedScenariosViewModel.cs
namespace Bobcat_BETA.ViewModels
{
public class MainViewModel : ViewModelBase
{
private ViewModelBase _currentViewModel;
readonly static SavedScenariosViewModel _savedScenarioViewModel = new SavedScenariosViewModel();
readonly static ScenarioEditorViewModel _scenarioEditorViewModel = new ScenarioEditorViewModel();
readonly static SimulatorViewModel _simulatorViewModel = new SimulatorViewModel();
public ViewModelBase CurrentViewModel
{
get
{
return _currentViewModel;
}
set
{
if (_currentViewModel == value)
return;
_currentViewModel = value;
RaisePropertyChanged("CurrentViewModel");
}
}
public MainViewModel()
{
CurrentViewModel = MainViewModel._savedScenarioViewModel;
SavedScenarioViewCommand = new RelayCommand(() => ExecuteSavedScenarioViewCommand());
ScenarioEditorViewCommand = new RelayCommand(() => ExecuteScenarioEidtorViewCommand());
SimulatorViewCommand = new RelayCommand(() => ExecuteSimulatorViewCommand());
}
public ICommand SavedScenarioViewCommand { get; private set; }
public ICommand ScenarioEditorViewCommand { get; private set; }
public ICommand SimulatorViewCommand { get; private set; }
private void ExecuteSavedScenarioViewCommand()
{
CurrentViewModel = MainViewModel._savedScenarioViewModel;
}
private void ExecuteScenarioEidtorViewCommand()
{
CurrentViewModel = MainViewModel._scenarioEditorViewModel;
}
private void ExecuteSimulatorViewCommand()
{
CurrentViewModel = MainViewModel._simulatorViewModel;
}
}
}
namespace Bobcat_BETA.ViewModels
{
public class SavedScenariosViewModel : ViewModelBase
{
public SavedScenariosViewModel()
{
}
ObservableCollection<ScenarioModel> _scenarioModels = new ObservableCollection<ScenarioModel>()
{
new ScenarioModel() {Name = "Scenario 0", ID = 000, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 1", ID = 001, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 2", ID = 002, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 3", ID = 003, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 4", ID = 004, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 5", ID = 005, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 6", ID = 006, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 7", ID = 007, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 8", ID = 008, Desc = "This will describe the Scenario Model."},
new ScenarioModel() {Name = "Scenario 9", ID = 009, Desc = "This will describe the Scenario Model."}
};
public ObservableCollection<ScenarioModel> ScenarioModels
{
get { return _scenarioModels; }
}
}
}
名称空间山猫_BETA.ViewModels
{
公共类SavedScenariosViewModel:ViewModelBase
{
公共存储的scenariosviewmodel()
{
}
ObservableCollection\u scenarioModels=新的ObservableCollection()
{
new ScenarioModel(){Name=“Scenario 0”,ID=000,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 1”,ID=001,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 2”,ID=002,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 3”,ID=003,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 4”,ID=004,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 5”,ID=005,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 6”,ID=006,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 7”,ID=007,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 8”,ID=008,Desc=“这将描述场景模型。”},
new ScenarioModel(){Name=“Scenario 9”,ID=009,Desc=“这将描述场景模型。”}
};
公共可观测收集场景模型
{
获取{return\u scenarioModels;}
}
}
}
SavedScenariosUserControl.xaml
<UserControl x:Class="Bobcat_BETA.UserControls.SavedScenariosUserControl"
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"
xmlns:vm="clr-namespace:Bobcat_BETA.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Dictionaries/MasterDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Style>
<DynamicResource ResourceKey="GeneralUserControl"/>
</UserControl.Style>
<Grid>
<Label Content="Saved Scenario Selection"
Style="{StaticResource GeneralLabel}" HorizontalAlignment="Left" Margin="26,30,0,0" VerticalAlignment="Top" Height="62" Width="345"/>
<Label Content="Chose Flight Model:"
Style="{StaticResource GeneralLabel2}"
HorizontalAlignment="Left" Margin="27,111,0,0" VerticalAlignment="Top" Height="43" Width="345"/>
<ListBox Style="{StaticResource GeneralListBox}"
HorizontalAlignment="Left" Height="509" Margin="27,154,0,0" VerticalAlignment="Top" Width="345"
ItemsSource="{Binding ScenarioModels}"/>
<Button Content="New"
Style="{StaticResource TransitionButton}"
HorizontalAlignment="Left" Margin="948,601,0,0" VerticalAlignment="Top" MinHeight="62" MinWidth="150" IsEnabled="True"
Command="{Binding ScenarioEditorViewCommand}"/>
<Button Content="Edit"
Style="{StaticResource TransitionButton}"
HorizontalAlignment="Left" Margin="401,519,0,0" VerticalAlignment="Top" MinHeight="62" MinWidth="150"
Command="{Binding SaveScenariosViewCommand}"/>
<Button Content="Load"
Style="{StaticResource TransitionButton}"
HorizontalAlignment="Left" Margin="401,601,0,0" VerticalAlignment="Top" MinHeight="62" MinWidth="150"
Command="{Binding SimulatorViewCommand}"/>
</Grid>
</UserControl>
如果有什么不清楚的地方,我也可以添加模型类,但是我假设您可以从正在发生的事情中做出推断。谢谢。您不能使用界面作为示例IChildLayout吗? 每个ViewModel继承此界面的
public interface IChildLayout:INotifyPropertyChanged
{
public MainWindows_ViewModel Parent;
}
在您的主Windows ViewModel中,您可以有如下内容
属性布局,当您单击按钮时会发生更改
public class MainWindows_ViewModel:INotifyPropertyChanged
{
public MainWindows_ViewModel()
{
//Here i set the default ViewModel
this.Child=new First_ViewModel(){Parent=this};
}
private IChildLayout _child;
public IChildLayout Child
{
get
{
return _child;
}
set
{
_child=value;
_child.Parent=this;
NotifyPropertyChanged("Child");
}
}
#region INotifyPropertyChangedMembers...
}
对于每个布局,您可以检索父窗口ViewModel(通过从其自己的ViewModel编辑“子”属性来切换布局非常重要…)
在主窗口(在xaml中)中放置一个UserControl,内容绑定到子属性,然后每次更改子属性时都会刷新该内容
<Windows>
<Windows.DataContext>
<local:MainWindows_ViewModel/>
</Windows.DataContext>
<UserControl Content={Binding Child}>
<UserControl.Resources>
<DataTemplate DataType="{x:Type ViewModels:First_ViewModel}">
<Controls:First_View DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:Second_ViewModel}">
<Controls:Second_View DataContext="{Binding}" />
</DataTemplate>
</UserControl.Resources>
</UserControl>
</Windows>
}
我希望这将对您有所帮助,我这样做是为了管理WPF应用程序中的不同选项卡。因此您的方法非常合理。为了获得该功能,您必须使用某些复杂的功能。我必须使用包含所有视图模型的“MainViewModel”。这些视图模型的行为使得当数据上下文切换到不同的视图模型时,相应的用户控件将更改为相应的视图。谢里登回答了我遵循的一个很好的例子。使用适当的数据模板和数据上下文切换将钩住您的app.xaml,处理起来就像魔术一样:D 我与Sheridan的示例不同(因为我不想创建单独的中继命令类/对象),实际上我使用mvvm light(galasoft)将消息从我的viewmodels发送到消息回“MainViewModel”,以切换其数据上下文。可以找到一个使用MVVM轻消息传递的好例子。从“子”视图模型发送消息,并将其注册到“MainViewModel”
祝你好运 这看起来合乎逻辑,所以我会尽我最大的努力让它工作。欢迎提供任何其他代码示例。谢谢。实际上,我的App.xaml的布局与您提到的第一个示例完全相同。我不是从BaseViewModel派生ViewModels,而是从MVVM Light派生ViewModelBase。不过我对Messenger有点迷茫。明天我会把我所有的课程都发到gander的网站上。好的!关于如何从MVVM Light派生ViewModelBase,您让我有点不知所措。但是,是的,发布你的代码,我会看一看。所以我还没有能够真正深入到你的代码太多的细节,但我从来没有得到我的ViewModelLocator工作。所以我删掉了那部分代码。相反,我将主窗口的datacontext设置为已设置的mainviewmodel。然后,可以将主窗口中的绑定绑定到“currentviewmodel”。现在您缺少的是消息传递系统。我使用NuGet获取用于MVVM轻消息传递的galasoft包。安装后,请遵循MVVM light messaging模式的示例。仅供参考:该模式将使用您的数据、消息等创建一个通用的“消息”类。封装要在该类中发送的消息。然后,创建解析该消息的函数,然后通过设置datacontex切换到适当的viewmodel
public class First_ViewModel:IChildLayout
{
public MainWindows_ViewModel Parent {get;set;}
public ICommand cmdBtn1click{get;set;}
private Pass_to_second_ViewModel()
{
//Here i change the Parent Child Property, it will switch to Second_View.xaml...
this.Parent.Child=new Second_ViewModel();
}
public First_ViewModel()
{
// Here i connect the button to the command with Prism...
this.cmdBtn1click=new DelegateCommand(()=>Pass_to_second_ViewModel());
}
#region INotifyPropertyChangedMembers...