First Problem
You're binding to a property called
MainWindowStatusIndicator
; you're raising a
PropertyChanged
event for a property called
MainWindowStatusIndicator
; but your property is
actually called
Results
.
If you look in the debug output window in Visual Studio, you'll see binding errors telling you that your viewmodel doesn't contain a property called
MainWindowStatusIndicator
.
Either change the name of the property to
MainWindowStatusIndicator
, or change the binding and the string in the
NotifyPropertyChanged
call to the correct property name.
Second Problem
Your
Button1_Click
method creates a new instance of your viewmodel class, sets a property on that new instance, and then throws it away.
A change to an instance property on one instance of a class will not affect any other instance of that class.
You have two options:
- Retrieve the current instance of the viewmodel class from the control's
DataContext
property, and change the property on that instance:
Private Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click
Dim context As ColorVM = TryCast(DataContext, ColorVM)
If context IsNot Nothing Then
context.MainWindowStatusIndicator = "..."
End If
End Sub
- Do it the MVVM way - remove the click event handler, and use an
ICommand
instead:
You'll need an ICommand
implementation which calls a function on your viewmodel. There are various options available - this is just a random one from a Google search:
Public Class DelegateCommand : Implements ICommand
Private m_canExecute As Func(Of Object, Boolean)
Private m_executeAction As Action(Of Object)
Private m_canExecuteCache As Boolean
Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements ICommand.CanExecuteChanged
Public Sub New(ByVal executeAction As Action(Of Object), ByVal canExecute As Func(Of Object, Boolean))
Me.m_executeAction = executeAction
Me.m_canExecute = canExecute
End Sub
Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute
Dim temp As Boolean = m_canExecute(parameter)
If m_canExecuteCache <> temp Then
m_canExecuteCache = temp
RaiseEvent CanExecuteChanged(Me, New EventArgs())
End If
Return m_canExecuteCache
End Function
Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
m_executeAction(parameter)
End Sub
End Class
Your viewmodel then exposes a property for the ICommand
implementation, which calls private methods on the viewmodel to perform the action when the button is clicked:
Public Class ColorVM : Implements INotifyPropertyChanged
Private _MainWindowStatusIndicator As String
Private _ChooseColorCommand As ICommand
Public Sub New()
Me._ChooseColorCommand = New DelegateCommand(AddressOf ChooseColor, AddressOf CanChooseColor)
End Sub
Public ReadOnly Property ChooseColorCommand As ICommand
Get
Return _ChooseColorCommand
End Get
End Property
Public Property MainWindowStatusIndicator As String
Get
Return _MainWindowStatusIndicator
End Get
Set(ByVal Value As String)
_MainWindowStatusIndicator = Value
NotifyPropertyChanged("MainWindowStatusIndicator")
End Set
End Property
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Private Sub ChooseColor(param As Object)
MainWindowStatusIndicator = "..."
End Sub
Private Function CanChooseColor(param As Object) As Boolean
Return True
End Function
End Class
Your XAML then binds to the ICommand
implementation, and doesn't use the Click
event at all:
<UserControl x:Class="SampleUserControl"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<Grid>
<Button x:Name="Button1" Command="{Binding Path=ChooseColorCommand}"/>
</Grid>
</UserControl>