[英]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.