I make a simple MVVM sample. I have main window with two user control pages. The main window have two event to change the view to two user control.
This is my main window XAML
<Window
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:MVVC_Binding"
xmlns:views="clr-namespace:MVVC_Binding.Views"
xmlns:viewModel="clr-namespace:MVVC_Binding.ViewModels"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="MVVC_Binding.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:Page1ViewModel}">
<views:Page1 />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:Page2ViewModel}">
<views:Page2/>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="Page1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding NavCommand}" CommandParameter="page1"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<TextBlock Text="Page2">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding NavCommand}" CommandParameter="page2"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</StackPanel>
<DockPanel Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Gainsboro">
<Grid x:Name="container" Background="Gainsboro" VerticalAlignment="Top">
<ContentControl Content="{Binding CurrentViewModel}"/>
</Grid>
</DockPanel>
</Grid>
</Window>
I am using the BindableBase class for my view model. This is my BindableBase class
namespace MVVC_Binding.Utilities
{
public class BindableBase : INotifyPropertyChanged
{
/// <summary>
/// Interface implementation
/// </summary>
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected virtual void SetProperty<T>(ref T member, T val, [CallerMemberName] string propertyName = null)
{
// Check for current set member and the new value
// If they are the same, do nothing
if (object.Equals(member, val)) return;
member = val;
// Invoke the property change event
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
In my main view model, just simple click event to change the view binding
private BindableBase _CurrentViewModel;
public BindableBase CurrentViewModel
{
get { return _CurrentViewModel; }
set
{
SetProperty(ref _CurrentViewModel, value);
}
}
private void OnNav(string destination)
{
switch (destination)
{
case "page2":
CurrentViewModel = page2;
break;
default:
CurrentViewModel = page1;
break;
}
}
The problem is in user control Page 2, when it is display, and the event in side of it does not change the TextBlock binding value, but the text can change during the view model constructor event.
Here is my page 2 XAML
<UserControl x:Class="MVVC_Binding.Views.Page2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MVVC_Binding.Views"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<TextBlock Name="txtPage2" Text="{Binding Page2Text}"></TextBlock>
<TextBlock Name="btn" Text="Click Button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding BtnCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</StackPanel>
</UserControl>
And here is the Page2ViewModel
namespace MVVC_Binding.ViewModels
{
public class Page2ViewModel : BindableBase
{
public MyICommand<string> BtnCommand { get; private set; }
public Page2ViewModel()
{
BtnCommand = new MyICommand<string>(OnBtnClick);
Page2Text = "Just a test";
}
private void OnBtnClick(string obj)
{
Page2Text = "Changing by button click";
}
private string _page2Text;
public string Page2Text
{
get { return _page2Text; }
set
{
_page2Text = value;
SetProperty(ref _page2Text, value);
}
}
}
}
Can you please see what I am doing wrong? Thanks so much
BindableBase. If you change yourSetPropertyto return aboolwithtruemeaning the value was updated, andfalseif it wasn't, you can do some really efficient property changing if you need extra logic in your setter. I use the same pattern, and it is very helpful. - Bradley UffnerPropertyChangedevent is set up and fired looks a little odd to me, but I'm not sure if it's really a problem, or just different than what I am used to. Have you used thisBindableBaseclass before with successful 2-way binding, or is this the first time you are trying to use it? - Bradley UffnerPropertyChangedevent to notify it of the new value. Try changing yourBindableBaseso that it looks like this and let me know if it makes any difference. If that works, I'll type up an answer for you. - Bradley Uffner