c# - MVVM Light - 用户控件作为 View

标签 c# xaml mvvm user-controls mvvm-light

我决定使用 MVVM Light 库来帮助设计 UI。经过大量的研究和反复试验,我还没有找到我正在寻找的答案。我用谷歌搜索并阅读了我能找到的每个 StackOverflow 问题,但是,我的问题似乎在 SO 上是独一无二的。

我想设计一个只有一个窗口的用户界面,并用不同的 View /用户控件填充它。我不希望在 UserControls 之间共享导航栏,也不希望弹出多个窗口。每个 View/UserControl 都应该绑定(bind)到它自己的 ViewModel,而 MainWindow 将绑定(bind)到一个 MainViewModel。

示例场景 - 带有 3 个用户控件的主窗口

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>

主窗口.xaml

<Window x:Class="Bobcat_BETA.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Bobcat - Version:0.00"
    DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid>
    <ContentControl Content="{Binding CurrentView}"/>
</Grid>

ViewModelLocator.cs

namespace Bobcat_BETA.ViewModels
{

    public class ViewModelLocator
    {

        private static MainViewModel _main;

        public ViewModelLocator()
        {
            _main = new MainViewModel();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
            "CA1822:MarkMembersAsStatic",
            Justification = "This non-static member is needed for data binding purposes.")]
        public MainViewModel Main
        {
            get
            {
                return _main;
            }
        }
    }
}

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

SavedScenariosViewModel.cs

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

    }
}

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>

如果有任何不清楚的地方,我也可以添加模型类,但我假设您可以从正在发生的事情中做出推断。谢谢。

最佳答案

所以你的方法很合理。为了获得该功能,您必须使用某些复杂的方法。我不得不使用包含所有 View 模型的“MainViewModel”。这些 View 模型的行为使得当数据上下文切换到不同的 View 模型时,相应的用户控件将更改为适当的 View 。 Sheridan 回答了我遵循的一个很好的例子 here .使用适当的数据模板连接到您的 app.xaml 中,数据上下文切换将像魔术一样处理 :D

在我与 Sheridan 的示例不同的地方(因为我不想创建单独的中继命令类/对象),我实际上使用 mvvm light (galasoft) 将消息从我的 View 模型发送到消息返回到“MainViewModel”以切换其数据上下文。可以找到使用 MVVM 轻量级消息传递的一个很好的例子 here .从“子” View 模型发送消息并将其注册到“MainViewModel”。

祝你好运!

关于c# - MVVM Light - 用户控件作为 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26264808/

相关文章:

wpf - 如何使滚动查看器在 WPF 中将高度设置为自动的情况下工作?

c# - 从 View 模型的构造函数调用异步方法

c# - 将参数传递给 MVVM 命令

c# - 带有 LinqToSQL 的 MVVM

wpf - WPF 中选定的文本颜色

c# - 函数分析问题 - Visual Studio 2010 Ultimate

c# - Automapper、泛型、dto 娱乐时间

c# - 使用Unity JsonUtility反序列化JSON数组获取序列化值失败

c# - 如何对自定义套接字 TCP 协议(protocol)使用证书身份验证?

C# WPF - 拖动并单击