Fill a Dockpanel with a WPF Webbrowser in MVVM pattern - c#

I want to write an HTML Editor. For this I want to have a MenuItem "New", which opens a WPF WebBrowser Control in a Dockpanel when it is clicked. Since now, I implement this function with CodeBehind. So my XML Code looks like this:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="661.94" Width="781.716">
<DockPanel x:Name="DockPanel1" HorizontalAlignment="Left" Height="629"
LastChildFill="False" VerticalAlignment="Top" Width="772">
<Menu DockPanel.Dock="Top" HorizontalAlignment="Right" Width="772">
<MenuItem Header="_Webseite">
<MenuItem Header="_Neu" Click="Neu_Click" />
<MenuItem Header="_Öffnen" Click="Oeffnen_Click"/>
<MenuItem Header="_Speichern" Click="Speichern_Click"/>
<Separator HorizontalAlignment="Left" Width="145"/>
<MenuItem Header="_Schließen" HorizontalAlignment="Left" Width="145"/>
</MenuItem>
<MenuItem Header="_Tools">
<MenuItem Header="_Button" Click="Select_Button"> </MenuItem>
</MenuItem>
</Menu>
<StackPanel></StackPanel>
</DockPanel>
And in the Code behind there is the following function implemented:
public partial class MainWindow : Window
{
public static IHTMLDocument2 doc;
public volatile WebBrowser webBrowser;
public MainWindow()
{
InitializeComponent();
}
private void Neu_Click(object sender, RoutedEventArgs e)
{
// create new WebBrowser for editing
webBrowser = new WebBrowser();
DockPanel.SetDock(webBrowser, Dock.Top);
this.DockPanel1.Children.Add(webBrowser);
string text = "<html><body></body></html>";
File.WriteAllText(#"C:\tmp\file.html", text);
webBrowser.Navigate("file:///C:/tmp/file.html");
doc = webBrowser.Document as IHTMLDocument2;
doc.designMode = "On";
}
But now I want to separate the View and the Model by using the MVVM pattern. Can anyone help me how to do it? I have real problems to understand the MVVM pattern with my Application.
Thanks for helping!

I handle methods on Controls with Command binding and the MVVM Light messenger class. In order for this to work you'll need to install the MVVM Light Nuget packages for WPF. With this approach the Click event on your MenuItem is bound to a RelayCommand in the ViewModel. That RelayCommand broadcasts a message ("MakeWebBrowser") which is accessible by any class subscribed to the messaging service. The View codebehind is subscribed to messaging, receives the message and fires the method that makes your WebBrowser.
View:
<MenuItem Header="_Neu" Command="{Binding MakeWebBrowserCommand}" />
ViewModel:
Declare the RelayCommand:
RelayCommand MakeWebBrowserCommand
{
get;
private set;
}
In your ViewModel constructor:
DoSomethingCommand = new RelayCommand(MakeWebBrowserCommandExecute);
Define the MakeWebBrowserCommandExecutemethod:
private void MakeWebBrowserCommandExecute()
{
Messenger.Default.Send(new NotificationMessage("MakeWebBrowser"));
}
View codebehind:
In your View's constructor, register for NotificationMessages:
Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
Define the NotificationMessageReceived method:
private void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == "MakeWebBrowser")
MakeWebBrowser();
}
Rename/define the method:
private void Neu_Click(object sender, RoutedEventArgs e)
to:
private void MakeWebBrowser()

Related

WPF command in code behind not firing

I'm working on a WPF application using the MVVM pattern and I'm still fairly new to .NET development. My understanding is that the View should set its data context to a ViewModel and then any data related processing should be done in the ViewModel while the UI part should be handled in the view (XAML or code behind).
So I have a menu with each menu item bound to a DelegateCommand (using Prism) declared and handled in the ViewModel with keyboard shortcuts and it works flawlessly. However, I wanted to bind a menu item to a command in the View's code behind file as it doesn't manupulate any data (it just shows or hide a panel).
View (XAML)
<Window x:Class="Editor.Views.MainWindow"
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:local="clr-namespace:Editor.Views"
xmlns:vm="clr-namespace:Editor.ViewModels"
mc:Ignorable="d"
x:Name="RootWindow"
WindowStartupLocation="CenterScreen"
Width="1200" Height="650">
<!-- Data Context -->
<Window.DataContext>
<vm:MainViewModel />
</Window.DataContext>
<!-- Keyboard Shortcuts -->
<Window.InputBindings>
<KeyBinding Modifiers="Control" Key="L" Command="{Binding ElementName=RootWindow, Path=ToggleLayersCommand}" />
</Window.InputBindings>
<!-- Main Menu -->
<Menu>
<MenuItem Header="View" Padding="5, 2">
<MenuItem Header="Toggle Layers Panel" InputGestureText="CTRL + L" Command="{Binding ElementName=RootWindow, Path=ToggleLayersCommand}" />
</MenuItem>
</Menu>
</Window>
View (Code behind)
public partial class MainWindow : Window
{
public DelegateCommand ToggleLayersCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
ToggleLayersCommand = new DelegateCommand(ToggleLayersCommand_OnExecuted, () => true);
}
private void ToggleLayersCommand_OnExecuted()
{
LayerListPanel.Visibility = (LayerListPanel.Visibility == Visibility.Collapsed) ? Visibility.Visible : Visibility.Collapsed;
}
}
I named the window in XAML to find the command in the View instead of the ViewModel when binding the Command attribute. It seems to find it since I'm getting intellisense but it never fires.
I could use a click event instead even though I'd rather use a command but then how to bind the keyboard shortcut to the event?
I would define the command inside the ViewModel and have it change a property public Visibility LayerListPanelVisibility (which should also be defined in the ViewModel). Then I would bind LayerListPanel.Visibility to this property.
Keep your code-behind as empty as possible.
The reason that the command is not found by your Binding is that ToggleLayersCommand is null when the Binding is resolved. It is only shortly after binding resolution that you assign the proper command to ToggleLayersCommand. However, the Binding will not be updated as your Viewmodel does not raise a PropertyChanged event.
If you want to keep your command in the View, you can either raise a PropertyChanged event when you have assigned the command or you assign the command before you call InitializeComponent:
public MainWindow()
{
ToggleLayersCommand = new DelegateCommand(ToggleLayersCommand_OnExecuted, () => true);
InitializeComponent();
}
I had same problem with binding command to keybinding. All I have done is give to a button its own name and from view code behind set command to yours.
My example looks like so:
<KeyBinding x:Name="ShowDetailsKeyBinding"
Key="D"
Modifiers="Control" />
Code behind:
ShowDetailsKeyBinding.Command = new DelegateCommand(ShowDetailsOperation);
I use this solution to run my animations, other way you should create command in yours ViewModel.
You have to use the ViewModel for command and not the View:
ViewModel:
public partial class MainViewModel
{
public DelegateCommand ToggleLayersCommand { get; private set; }
public MainViewModel()
{
ToggleLayersCommand = new DelegateCommand(ToggleLayersCommand_OnExecuted, () => true);
}
private void ToggleLayersCommand_OnExecuted()
{
LayerListPanel.Visibility = (LayerListPanel.Visibility == Visibility.Collapsed) ? Visibility.Visible : Visibility.Collapsed;
//THIS WILL PROBABLY NOT WORK...
//You can use another public property to change your visibility.
// Create a public visibility and bind it to the correct item
}
}
XAML:
<Menu>
<MenuItem Header="View" Padding="5, 2">
<MenuItem Header="Toggle Layers Panel" InputGestureText="CTRL + L" Command="{Binding Path=ToggleLayersCommand}" />
</MenuItem>
</Menu>

WPF bind a dynamic generated slider to function

First: Not a duplicate of Binding Button click to a method --- it's about button, and Relay command can't pass the arguments I need
Also, not a duplicate of How do you bind a Button Command to a member method? - it's a simple method with no arguments - nothing to do with my question.
Obviously (but just to make sure and avoid trolls) not a duplicate of this either Silverlight MVVM: where did my (object sender, RoutedEventArgs e) go?.
Now after clearing this (sorry, I am just really sick of being marked as "duplicate" by people who didn't understand my question), let's talk about the issue: :D
I am trying to bind a generated slider (using data template) to an event (value changed), I know it's impossible to bind an event and I must use ICommand, but I don't know how to get the event arguments to the command function, this is the xaml relevant code: (without the binding since it doesnt work)
<Slider Grid.Column="1" Grid.Row="1" Height="30" IsSnapToTickEnabled="True" Maximum="100" SmallChange="1" IsMoveToPointEnabled="True"/>
And this is the function I want it to be binded to:
public void vibrationSlider_move(object Sender, RoutedPropertyChangedEventArgs<double> e)
{
VibrationValue = (byte)e.NewValue;
SendPacket(cockpitType, (byte)Index.VibrationSlider, VibrationValue);
}
As you can see, I need to use the 'e' coming with the event, I have no idea how to reach it without using the "ValueChanged" slider event.
Notes:
Please don't tell me to add the "ValueChanged" attribute like this:
<Slider ValueChanged="VibrationSlider_move"/>
:)
It's a generated dynamic slider using DataTemplate with an observableCollection, the function isn't in the window.cs file, therefore just using an event is not possible.
Thank you.
You can use the MVVMLight Toolkit, which allows to send the EventArgs as CommandParameter to the ViewModel:
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<cmd:EventToCommand Command="{Binding ValueChangedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
In your command.Execute method, you now get an object as parameter which you just have to parse to the correct type...
You could create an extension
public partial class Extensions
{
public static readonly DependencyProperty ValueChangedCommandProperty = DependencyProperty.RegisterAttached("ValueChangedCommand", typeof(ICommand), typeof(Extensions), new UIPropertyMetadata((s, e) =>
{
var element = s as Slider;
if (element != null)
{
element.ValueChanged -= OnSingleValueChanged;
if (e.NewValue != null)
{
element.ValueChanged += OnSingleValueChanged;
}
}
}));
public static ICommand GetValueChangedCommand(UIElement element)
{
return (ICommand)element.GetValue(ValueChangedCommandProperty);
}
public static void SetValueChangedCommand(UIElement element, ICommand value)
{
element.SetValue(ValueChangedCommandProperty, value);
}
private static void OnSingleValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
var element = sender as Slider;
var command = element.GetValue(ValueChangedCommandProperty) as ICommand;
if (command != null && command.CanExecute(element))
{
command.Execute(element);
e.Handled = true;
}
}
}
which then can be used in xaml as below.
<Slider Minimum="0" Maximum="100" local:Extensions.ValueChangedCommand="{Binding ValueChangedCommand}"/>
As #Philip W stated, you could use e.g. MVVMLight to help dealing with MVVM pattern and with your problem at hand.
You could, for example, have a XAML with DataTemplate and Slider like so:
<Window x:Class="WpfApplication1.MainWindow"
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:local="clr-namespace:WpfApplication1"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:command="http://www.galasoft.ch/mvvmlight"
mc:Ignorable="d"
Title="MainWindow"
Height="250"
Width="250">
<Window.Resources>
<DataTemplate x:Key="SomeTemplate">
<StackPanel Margin="15">
<!-- Wrong DataContext can drive you mad!1 -->
<StackPanel.DataContext>
<local:SomeTemplateViewModel />
</StackPanel.DataContext>
<TextBlock Text="This is some template"/>
<Slider
Height="30"
IsSnapToTickEnabled="True"
Maximum="100"
SmallChange="1"
IsMoveToPointEnabled="True">
<!-- Bind/pass event as command -->
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<command:EventToCommand
Command="{Binding Mode=OneWay, Path=ValueChangedCommand}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
<!-- Show current value, just for sake of it... -->
<TextBlock
Text="{Binding Value}"
FontWeight="Bold"
FontSize="24">
</TextBlock>
</StackPanel>
</DataTemplate>
</Window.Resources>
<ContentControl ContentTemplate="{StaticResource SomeTemplate}" />
</Window>
So basically you bind desired event to named Command and pass EventArgs to it as parameter. Then in your ViewModel, being the DataContext of you Slider, you handle the event-passed-as-command.
public class SomeTemplateViewModel : ViewModelBase
{
private double _value;
public SomeTemplateViewModel()
{
// Create command setting Value as Slider's NewValue
ValueChangedCommand = new RelayCommand<RoutedPropertyChangedEventArgs<double>>(
args => Value = args.NewValue);
}
public ICommand ValueChangedCommand { get; set; }
public double Value
{
get { return _value; }
set { _value = value; RaisePropertyChanged(); } // Notify UI
}
}
This would give you something similar to this.
Since your slider is dynamically generated, nothing prevents you from adding your ValueChanged event at a later time:
XAML:
<Slider x:Name="slider" HorizontalAlignment="Left" Margin="10,143,0,0" VerticalAlignment="Top" Width="474" Grid.ColumnSpan="2" />
Code-behind:
public MainWindow()
{
InitializeComponent();
// it is a good idea to not allow designer to execute custom code
if (DesignerProperties.GetIsInDesignMode(this))
return;
slider.ValueChanged += Slider_ValueChanged;
}
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
// do your stuff here
}
Checking design mode is not simple in any context, as pointed out here.

WPF MenuItem grayed out when binding Command

I'm trying to hook up commands to context menu items in a TaskbarIcon but everytime I do, they become grayed out.
Here's the XAML:
<ResourceDictionary
xmlns:local="clr-namespace:Stickie.StickieNotes.WPFGUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="http://www.hardcodet.net/taskbar"
>
<!-- Globally declared notify icon -->
<tb:TaskbarIcon x:Key="MyNotifyIcon">
<tb:TaskbarIcon.ContextMenu>
<ContextMenu>
<MenuItem Header="Open Settings" Command="local:App.OpenSettingsCommand"
CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
<MenuItem Header="New Note"/>
<MenuItem Header="Exit" Command="local:App.ExitApplicationCommand"
CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>
</tb:TaskbarIcon.ContextMenu>
</tb:TaskbarIcon>
And my backing CS:
namespace Stickie.StickieNotes.WPFGUI
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
static App()
{
initializeCommands();
}
static void initializeCommands()
{
Type ownerType = typeof (App);
OpenSettingsCommand = new RoutedCommand("OpenSettings", ownerType);
ExitApplicationCommand = new RoutedCommand("ExitApplication", ownerType);
CommandBinding openSettings = new CommandBinding(OpenSettingsCommand, OpenSettingsExecuted, OpenSettingCanExecute);
CommandBinding exitApplication = new CommandBinding(ExitApplicationCommand, ExitApplicationExecuted, ExitApplicationCanExecute);
CommandManager.RegisterClassCommandBinding(ownerType,openSettings);
CommandManager.RegisterClassCommandBinding(ownerType,exitApplication);
}
public static RoutedCommand OpenSettingsCommand;
public static RoutedCommand ExitApplicationCommand;
private static void ExitApplicationCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private static void OpenSettingCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private static void ExitApplicationExecuted(object sender, ExecutedRoutedEventArgs e)
{
Application.Current.Shutdown(0);
}
private static void OpenSettingsExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (Application.Current.MainWindow != null)
{
Application.Current.MainWindow.Show();
}
}
}
}
I've been playing around with it and looking around a ton but I can't seem to get it to work. Does anyone have a possible solution?
From this article:
ContextMenus are separate windows with their own VisualTree and LogicalTree.
[...] the CommandManager searches for CommandBindings within the current focus scope. If the current focus scope has no command binding, it transfers the focus scope to the parent focus scope. When you startup your application the focus scope is not set. You can check this by calling FocusManager.GetFocusedElement(this) and you will receive null.
The simplest solution is to initially set the logical focus:
public Window1()
{
InitializeComponent();
// Set the logical focus to the window
Focus();
}
Another solution is to manually bind the CommandTarget to the parent ContextMenu.
<MenuItem Header="Cut" Command="Cut" CommandTarget="
{Binding Path=PlacementTarget,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ContextMenu}}}"/>

WPF Context Menu, Copy Menu Item is grayed out

I have a ListView databinded to a ObservableCollection of a class. I'm trying to add a "Copy" menu item to the ListView like so:
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Command="{x:Static ApplicationCommands.Copy}"></MenuItem>
<MenuItem Command="{x:Static ApplicationCommands.Copy}"
CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"></MenuItem>
</ContextMenu>
</ListView.ContextMenu>
Now when i right click a menu item.. the menu comes up but the Copy is grayed out.. my educated guess is that it thinks there's nothing for it to copy.. but that doesn't make sense because when i right click a listbox item.. i'm technically selecting something for it to copy.. and the listbox item is selected as i'm doing this..I just want it to copy the selected text in the ListView.
What do I have to do to get this to work? Overwrite a copy class in my class that's binded to the Listview? I tried googling and not getting very far.
I've just put together an example that works for me:
<Window.CommandBindings>
<CommandBinding
Command="ApplicationCommands.Copy"
CanExecute="CommandBinding_CanExecute"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<Window.Resources>
<ContextMenu x:Key="MyContextMenu">
<MenuItem Header="Copy" Command="ApplicationCommands.Copy"/>
</ContextMenu>
<Style x:Key="MyItemContainerStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="ContextMenu" Value="{StaticResource MyContextMenu}" />
</Style>
</Window.Resources>
<Grid>
<ListView x:Name="MyListView" ItemContainerStyle="{StaticResource MyItemContainerStyle}"/>
</Grid>
Then in the code behind:
// Test class with a single string property
private class MyData
{
public String Name { get; set; }
public MyData(String name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
}
public MainWindow()
{
InitializeComponent();
// Create some test data
ObservableCollection<MyData> names = new ObservableCollection<MyData>();
names.Add(new MyData("Name 1"));
names.Add(new MyData("Name 2"));
names.Add(new MyData("Name 3"));
MyListView.ItemsSource = names;
}
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
Clipboard.SetText(MyListView.SelectedItem.ToString());
}
This works whether you select Copy from the context menu, or use Ctrl+C
Without having you rewrite everything, the thing to note about Gary's sample is the presence of a CanExecute statement, which is what controls the enabling/disabling of commands. You should look in to the proper command structure some more, because I think you're missing the real power of the command.
https://msdn.microsoft.com/en-us/library/ms753200%28v=vs.110%29.aspx

How to switch views within one window from button in child view in WPF MVVM?

I have an issue with switching views in a WPF MVVM app.
When clicking on menu items defined in the main view, switching works fine.
When clicking on a button in a child view, switching does not work as expected.
If I set contentcontrol in child view (where the button is) as well as parent view,
the child view gets displayed mixed with previous displayed view, a button from one view and background from the one I want to switch to.
Without it, the debugger shows something happening, similar steps in the ViewModelBase class to what happened when choosing from the menu mentioned above but no visual changes in the window.
I have commands in a ViewmodelBase (that all viewmodels inherit from either directly or through a mainviewmodel) class that gets called from bindings such as in the XAML above.
CurrentViewModel is a property in ViewModelBase that is used to determine which view gets displayed. In the constructor of ViewModelBase i set commands for example:
CategoryVMCommand = new RelayCommand(() => ExecuteCategoryVMCommand());
(RelayCommand from the line above comes from the MVVM light framework,
although its not necessary for the solution to use that framework)
I found many tutorials and answers for similar problems, but couldnt get any of them to work. For example I tried, without success, using IOC for a similar problem in the below link:
MVVM Main window control bind from child user control
Here are some of the code involved and description of what Im doing:
Main Window:
<Grid>
<ContentControl Content="{Binding CurrentViewModel}" />
<DockPanel Margin="0,0,0,50">
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="_Open" Command="{Binding CategoryVMCommand}"/>
<MenuItem Header="_Close"/>
<MenuItem Header="_Save"/>
</MenuItem>
<MenuItem Header="_New">
<MenuItem Header="_Create" Command="{Binding MainControlVMCommand}"/>
</MenuItem>
</Menu>
<StackPanel></StackPanel>
</DockPanel>
</Grid>
</Window>
Then I select Menu item New, the following view is displayed:
<UserControl x:Class="WpfApplication1.MainControl"
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"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<!--<ContentControl Content="{Binding CurrentViewModel, Mode=OneWay}" />-->
<TextBlock HorizontalAlignment="Left" Margin="10,20,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="39" Width="144" FontSize="24"><Run Language="en-gb" Text="TITLE"/><LineBreak/><Run Language="en-gb"/></TextBlock>
<Button Content="Open category" HorizontalAlignment="Left" Margin="10,136,0,0" VerticalAlignment="Top" Width="153" Height="63" Command="{Binding CategoryVMCommand}" />
<Button Content="Create new category" HorizontalAlignment="Left" Margin="10,218,0,0" VerticalAlignment="Top" Width="153" Height="63"/>
<ListBox HorizontalAlignment="Left" Height="145" Margin="293,136,0,0" VerticalAlignment="Top" Width="201" Background="#FFDDDDDD"/>
<TextBlock HorizontalAlignment="Left" Margin="293,107,0,0" TextWrapping="Wrap" Text="Recently Used" VerticalAlignment="Top" FontSize="18"/>
</Grid>
</UserControl>
button open category clicked, and Currentviewmodel set code executes (depending on ContenControl in MainControl view being commented out or not either
return or assigned), then The ExecuteCategoryCommand get executed. Then the line with the expected command in ViewModelBase constructor executes, although
either no change or the mixed result i mentioned originally
ViewModelBase class:
namespace ViewModel
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ViewModelBase _currentViewModel;
public ICommand CategoryVMCommand { get; private set; }
public ICommand MainControlVMCommand { get; private set; }
protected void NotifyPropertyChanged( String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public ViewModelBase()
{
MainControlVMCommand = new RelayCommand(() => ExecuteMainControlVMCommand());
CategoryVMCommand = new RelayCommand(() => ExecuteCategoryVMCommand());
}
public ViewModelBase CurrentViewModel
{
get
{
return _currentViewModel;
}
set
{
if (_currentViewModel == value)
return;
_currentViewModel = value;
NotifyPropertyChanged("CurrentViewModel");
}
}
protected void ExecuteCategoryVMCommand()
{
CurrentViewModel = null;
CurrentViewModel = new CategoryVM();
}
protected void ExecuteMainControlVMCommand()
{
CurrentViewModel = null;
CurrentViewModel = new MainControlVM();
}
}
}
So my question is how can I click the button in the child view, send command from ViewModelBase, set CurrentViewModel, and successfully switch views within one window without any visual remains of the previously displayed view?
Thanks for any help.

Categories