WPF 用户控件中的命令

Commands in WPF UserControls

我只是想了解 WPF 和 MVVM,但我完全糊涂了。 实际上我需要帮助完成以下任务:

我有一个带有菜单的主窗口。从这个菜单中,我想将一些数据加载到嵌套在用户控件中的树视图中。

据我目前所学,我应该使用命令。
我在哪里定义它们?

假设我有菜单,我会在菜单中使用'inside the MainWindow.xaml.<br> I also would (of course) implement theCommand`-属性。

执行代码应嵌套在单独的 class 或需要数据的 UserControl 的代码隐藏内。

这是我的用户控件:

namespace PlcGenerator.Views
{
  public partial class ProjectView : UserControl
  {
    public static RoutedCommand cmdLoadEcad = new RoutedCommand();

    public ProjectView()
    {
        InitializeComponent();
    }

    private void CanExecuteCmdLoadEcad(object sender, CanExecuteRoutedEventArgs e) 
    {
        e.CanExecute = true;
    }

    private void ExecutedCmdLoadEcad(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("Command executed.");
    }
  }
}

现在这是主窗口的(简化)部分:

<ribbon:RibbonWindow
x:Class="PlcGenerator.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ribbon="clr-namespace:System.Windows.Controls.Ribbon;assembly=System.Windows.Controls.Ribbon"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:PlcGenerator"
    xmlns:viewmodels="clr-namespace:PlcGenerator.ViewModels"
    xmlns:views="clr-namespace:PlcGenerator.Views"
    mc:Ignorable="d"
    Loaded="Window_Loaded"
    Closing="ClosingApp"
    Title="Plc Generator" Height="600" Width="1200">
<Window.CommandBindings>
    <CommandBinding Command="{x:Static views:ProjectView.cmdLoadEcad}"
                    Executed="ProjectView.ExecutedCmdLoadEcad"
                    CanExecute="ProjectView.CanExecuteCmdLoadEcad"/>
</Window.CommandBindings>
<Window.Resources>
    <DataTemplate x:Name="settingsViewTemplate" DataType="{x:Type viewmodels:SettingsViewModel}">
        <views:SettingsView DataContext="{Binding}"/>
    </DataTemplate>
    <DataTemplate x:Name="projectsViewTemplate" DataType="{x:Type viewmodels:ProjectViewModel}">
        <views:ProjectView DataContext="{Binding ProjectVM, Source={StaticResource Locator}}"/>
    </DataTemplate>
</Window.Resources>
<DockPanel LastChildFill="True">

    <ribbon:Ribbon DockPanel.Dock="Top">
        <Ribbon.ApplicationMenu>
            <RibbonApplicationMenu SmallImageSource="Icons/ApplicationMenu.png">
                <RibbonApplicationMenuItem Header="Neues Projekt" ImageSource="Icons/NewEntry.png" Command="{x:Static views:ProjectView.cmdLoadEcad}"/>
            </RibbonApplicationMenu>
        </Ribbon.ApplicationMenu>
    </ribbon:Ribbon>

        <!-- Fensterinhalt-->
    <ContentControl Margin="5" Content="{Binding}"/>
</DockPanel>

这里出现错误,找不到命令元素,我想是因为它不在代码隐藏 MainWindow 中?

那么我怎样才能在单独的 class 或用户控件中从 MainWindow-Menu 获得该命令?

我真的很闲!

UPDATE(如第一条评论中所述,我试图理解链接的答案):

我创建了一个 ViewModelLocator:

using PlcGenerator.ViewModels;

namespace PlcGenerator
{
    public class ViewModelLocator
    {
        public ViewModelLocator()
        {
            this.ProjectVM = new ProjectViewModel();
            this.SettingsVM = new SettingsViewModel();
        }
        public ProjectViewModel ProjectVM{ get; set; }
        public SettingsViewModel SettingsVM { get; set; }
    }
}

我想让它对所有视图和控件可用,所以我将它插入 App.xaml:

<Application x:Class="PlcGenerator.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:PlcGenerator"
         StartupUri="MainWindow.xaml">
  <Application.Resources>
    <local:ViewModelLocator x:Key="Locator" />
  </Application.Resources>
</Application>

第一个问题,当它位于 ViewModel 命名空间时,我无法将其插入。这是如何工作的?

现在,在使用命令执行任何操作之前,我想在显示没有用户控件的主窗口时填充虚拟机,调用菜单事件。所以我在 MainWindow 的代码隐藏中写了以下内容:

public MainWindow()
{
    InitializeComponent();
    this.DataContext = new ViewModelLocator();
}

public MnuOpenProject(object sender, RoutedEventArgs e)
{
    //How can I now access the ProjectViewModel (ProjectVM) of the Datacontext?
}

在 MnuOpenProject 方法中,我无法访问 DataContext.ProjectVM。如何在 VM 定位器中创建此对象?

我解决了之后,我会继续命令。然后我会把所有的逻辑,比如在视图模型中打开一个项目吗?

下次尝试

还在 <Window.Resources... 部分编辑了 <DataTemplate...,见上文

必须这样吗?:

public partial class MainWindow : RibbonWindow
{
    #region Data
    public ViewModelLocator viewModelLocator;
    #endregion

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModelLocator();

        viewModelLocator = (ViewModelLocator)this.DataContext;

    }

    public MnuOpenProject(object sender, RoutedEventArgs e)
    {
        viewModelLocator.ProjectVM.Name = "ProjectName";
    }
}

还有所有其他视图?

如果您尝试使用 MVVM 模式,则需要有一个 ViewModel,您可以在其中定义命令。您需要将视图中的 DataContext 设置为 ViewModel - 如果您需要帮助,请参阅 this 答案。

您正在使用 App.xaml 中的以下资源创建 ViewModelLocator class 的实例:

<local:ViewModelLocator x:Key="Locator" />

然后您可以直接在 XAM 标记中将 window 的 DataContext 绑定到 ViewModelLocator 的 属性,如下所示:

<Window ... DataContext="{Binding ProjectViewModel, Source={StaticResource Locator}}" />

使用此方法,无需在代码隐藏中以编程方式设置 DataContext

DataContext 设置为从 ViewModelLocator 返回的视图模型实例后,您可以绑定到任何 public 属性 视图模型在视图中,例如:

<TextBlock Text="{Binding SomePropertyInProjectViewModel" />