I'm just trying to understand WPF and MVVM and I am totally confused. Actually I need help with the following task:
I have a MainWindow, that carries a menu. From this menu, I want to load some data into a treeview, that is nested inside a usercontrol.
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.
The code for Execution should be nested inside a seperate class or inside the codebehind of the UserControl, that needs the data.
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?
So how can I get that command work from MainWindow-Menu inside a separate class or usercontrol?
I'm really off!
UPDATE (as mentioned in first comment, I tried to understand the linked answer):
I created a 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:
<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. 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. So I wrote the following in codebehind of 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. How do I create this object inside the VM-locator?
After I solve that, I will go on with commands. Will I then put all the logic, like opening a project inside the Viewmodels?
NEXT TRY
also edited <DataTemplate...
in the <Window.Resources...
-section, see above
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
:
<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:
<Window ... DataContext="{Binding ProjectViewModel, Source={StaticResource Locator}}" />
Using this approach, there is no need to set the DataContext
programmatically in the code-behind.
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:
<TextBlock Text="{Binding SomePropertyInProjectViewModel" />
You need to have a ViewModel where you define the command if you are trying to use the MVVM pattern. You need to set the DataContext in the View to the ViewModel - if you need help doing this, see this answer.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.