简体   繁体   English

WPF UserControls 中的命令

[英]Commands in WPF UserControls

I'm just trying to understand WPF and MVVM and I am totally confused.我只是想了解 WPF 和 MVVM,我完全糊涂了。 Actually I need help with the following task:实际上,我需要以下任务的帮助:

I have a MainWindow, that carries a menu.我有一个带有菜单的 MainWindow。 From this menu, I want to load some data into a treeview, that is nested inside a usercontrol.从此菜单中,我想将一些数据加载到嵌套在用户控件中的 treeview 中。

As I learned so far, I should use commands.据我所知,我应该使用命令。
Where do I define them?我在哪里定义它们?

Assuming I have the menu, I would use ' inside the MainWindow.xaml.<br> I also would (of course) implement the Command`-property inside the menu.假设我有菜单,我会inside the MainWindow.xaml.<br> I also would (of course) implement the Command 属性。

The code for Execution should be nested inside a seperate class or inside the codebehind of the UserControl, that needs the data.执行代码应该嵌套在单独的 class 或需要数据的 UserControl 的代码隐藏中。

This is my 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.");
    }
  }
}

Now this is a (reduced) part of the mainWindow:现在这是主窗口的(减少的)部分:

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

Here I get the error, that the command-element is not found, I think because it's not located in the codebehind MainWindow?在这里我得到错误,找不到命令元素,我想是因为它不在代码隐藏 MainWindow 中?

So how can I get that command work from MainWindow-Menu inside a separate class or usercontrol?那么如何在单独的 class 或用户控件中从 MainWindow-Menu 获取该命令?

I'm really off!我真的不行了!

UPDATE (as mentioned in first comment, I tried to understand the linked answer):更新(如第一条评论中所述,我试图理解链接的答案):

I created a ViewModelLocator:我创建了一个 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; }
    }
}

I wanted to make it available for all views and controls, so I inserted it into App.xaml:我想让它可用于所有视图和控件,所以我将它插入到 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>

First problem, I wasn't able to get it inserted while it was located in ViewModel-namespace.第一个问题,当它位于 ViewModel 命名空间中时,我无法插入它。 How does this work?这是如何运作的?

Now, before doing anything with commands, I'd like to fill the VMs while MainWindow is shown without UserControls, invoking a menu-event.现在,在使用命令执行任何操作之前,我想在 MainWindow 显示时没有 UserControls 时填充 VM,调用菜单事件。 So I wrote the following in codebehind of MainWindow:所以我在 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?
}

In the MnuOpenProject-method, I didn't manage to have any access to DataContext.ProjectVM.在 MnuOpenProject 方法中,我无法访问 DataContext.ProjectVM。 How do I create this object inside the VM-locator?如何在 VM 定位器中创建此 object?

After I solve that, I will go on with commands.解决这个问题后,我将使用命令打开 go。 Will I then put all the logic, like opening a project inside the Viewmodels?然后我会把所有的逻辑,比如在 Viewmodels 中打开一个项目?

NEXT TRY下一次尝试

also edited <DataTemplate... in the <Window.Resources... -section, see above还在<Window.Resources...部分编辑了<DataTemplate... ,见上文

Is that the way it has to be?:必须这样吗?:

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

And also in all other views?以及所有其他观点?

You are creating an instance of the ViewModelLocator class using the following resource in the in App.xaml :您正在使用 App.xaml 中的以下资源创建ViewModelLocator App.xaml的实例:

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

You could then bind the DataContext of the window to a property of the ViewModelLocator directly in the XAM markup like this:然后,您可以直接在 XAM 标记中将 window 的DataContext绑定到ViewModelLocator的属性,如下所示:

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

Using this approach, there is no need to set the DataContext programmatically in the code-behind.使用这种方法,无需在代码隐藏中以编程方式设置DataContext

Once you have set the DataContext to an instance of a view model returned from the ViewModelLocator , you can bind to any public property of the view model in the view, eg:DataContext设置为从ViewModelLocator返回的视图 model 的实例后,您可以绑定到视图中视图 model 的任何公共属性,例如:

<TextBlock Text="{Binding SomePropertyInProjectViewModel" />

You need to have a ViewModel where you define the command if you are trying to use the MVVM pattern.如果您尝试使用 MVVM 模式,则需要在其中定义命令的 ViewModel。 You need to set the DataContext in the View to the ViewModel - if you need help doing this, see this answer.您需要将 View 中的 DataContext 设置为 ViewModel - 如果您需要帮助,请参阅答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM