There are many CodeProject articles about other MVVM frameworks, but almost nothing with WPF and the MVVM Toolkit. So I started to create this document.
Introduction
This tip and the demo is about getting started using the MVVM Toolkit and some self-created interface
s / service
s for MessageBox
and some dialog
s.
Background
There are many CodeProject articles about other MVVM frameworks, but almost nothing with WPF and the MVVM Toolkit. So I started to create this document.
I will not describe and explain the complete demo project. The focus is on how to test some of the features.
MVVM Structure / Features
The MVVM Toolkit is from Microsoft and also some of the other used features are not my own: Sources as listed in the Credits / Reference section.
Here is a quick overview of the contents:
- MVVM Toolkit and .NET 4.7
RelayCommand
OnPropertyChanged
ObservableRecipient
(Messenger
and ViewModelBase
) DependencyInjection
(to run MsgBox
and Dialog
s as a service
) ObservableCollection
(for Credits Listbox
)
Ribbon
Menu Service
s / dialog
s - Using
ICommand
to bind button
s to the ViewModel
Installation of the MVVM Toolkit
With the installation of the NuGet package of the MVVM Toolkit, it installs 6 or 7 other packages.
Introduction to the MVVM Toolkit - Windows Community Toolkit | Microsoft Docs
For DependencyInjection
, we need to install another NuGet package:
And I made interface
s / service
s for MsgBox
and some dialog
s.
DependencyInjection
manages to start the following dialog
s independent from the viewmodel
s:
MsgBoxService
DialogVM
OpenFileDlgVM
SaveAsFileDlgVM
SearchDlgVM
This allows the usage of custom Messagebox
es / dialog
s as well as Unit Testing.
MainWindow Concept and Code
MainWindow
hosts the Ribbon
.
Below that, there is a Tabcontrol
, the structure is like this:
Application
Registering the service
s / viewmodel
s is in the Application code behind.
There is also code for Restore QuickAccessToolBar
State when the application
starts and saving QAT State when the App closes.
Mod_Public
Mod_Public
includes Property
sAppPath
and Public Sub
ErrHandler
:
Public Property sAppPath As String
Public Sub ErrHandler(sErr As String)
IO.File.AppendAllText(sAppPath & "\Log.txt", _
String.Format("{0}{1}", Environment.NewLine, Now.ToString & "; " & sErr))
Dim msgBoxService As IMsgBoxService = Ioc.[Default].GetService(Of IMsgBoxService)()
msgBoxService.Show("Unexpected error:" & vbNewLine & _
vbNewLine & sErr,,, Windows.MessageBoxImage.Error)
End Sub
MVVM Pattern - Details
From the WPF Ribbon
’s point of view, the data structure / model
is simple:
The Usercontrol
has menu items / ribbon buttons which work together with the TextBox
and other control
s.
That is what we see in model class TextData
.
Model class
called TextData
Imports System.Windows.Controls.Ribbon
Public Class TextData
Inherits ObservableRecipient
Implements INotifyPropertyChanged
Private _AppPath As String
Private _text As String
Private _NotifyTest As RibbonTextBox
Private _readText As String
Private _ActiveTextBox As TextBox
Dim _MyRibbonWPF As Ribbon
Dim _MyMainWindow As MainWindow
Public Sub New()
End Sub
Public Property MyMainWindow As MainWindow
Get
Return _MyMainWindow
End Get
Set(value As MainWindow)
_MyMainWindow = value
End Set
End Property
Public Property MyRibbonWPF() As Ribbon
Get
Return _MyRibbonWPF
End Get
Set(value As Ribbon)
_MyRibbonWPF = value
End Set
End Property
Public Property NotifyTestbox As RibbonTextBox
Get
Return _NotifyTest
End Get
Set(value As RibbonTextBox)
_NotifyTest = value
End Set
End Property
Public Property GetText As String
Get
Return _text
End Get
Set(value As String)
_text = value
OnPropertyChanged("GetText")
End Set
End Property
Public Property ReadText As String
Get
Return _readText
End Get
Set(value As String)
_readText = value
GetText = _readText
OnPropertyChanged("ReadText")
End Set
End Property
Public Property ActiveTextBox() As TextBox
Get
Return _ActiveTextBox
End Get
Set(value As TextBox)
_ActiveTextBox = value
End Set
End Property
End Class
ViewModel
class called TestingViewModel
The class called TestingViewModel
contains properties, ICommand
s and methods for the testing of some MVVM features.
It contains also code for the ObservableCollection
(Of Credits), which is used for the Listview
with the References / Credits for this article.
Putting Things Together
DependencyInjection or ServiceInjection
As already mentioned, there is some code for this in code behind of the Application.
Save File Dialog Example with ISaveAsFileDlgVM
It uses interface ISaveAsFileDlgVM
and service / viewmodel SaveAsFileDlgVM
.
Dim cmdSAFD As New RelayCommand(AddressOf SaveAsFileDialog)
SaveAsFileDlgCommand = cmdSAFD
Private Sub SaveAsFileDialog()
Dim dialog As ISaveAsFileDlgVM = Ioc.[Default].GetService(Of ISaveAsFileDlgVM)()
dialog.SaveAsFileDlg(_textData.GetText)
End Sub
And, very important, Command="{Binding SaveAsFileDlgCommand}"
in the XAML file.
<RibbonButton x:Name="SaveAs" Content="RibbonButton" HorizontalAlignment="Left"
Height="Auto" Margin="94,24,-162,-70" VerticalAlignment="Top"
Width="80" Label=" Save As" KeyTip="S"
AutomationProperties.AccessKey="S"
AutomationProperties.AcceleratorKey="S"
SmallImageSource="Images/save16.png"
CanAddToQuickAccessToolBarDirectly="False"
ToolTipTitle="Save As" Command="{Binding SaveAsFileDlgCommand}"/>
From the Ribbon
, you can start and test other dialog
s or the messagebox
with:
- Open Dialog
- Search (only a dummy dialog)
OpenFileDialog
- Tab Help > Info
Messenger Test
It is important to add Inherits ObservableRecipient
, this and other details are described in ObservableObject - Windows Community Toolkit | Microsoft Docs.
„View specific messages should be registered In the Loaded Event Of a view And deregistered In the Unloaded Event To prevent memory leaks And problems multiple callback registrations“.
We send a msg
from Class OpenFileDlgVM
:
Public Class OpenFileDlgVM
Inherits ObservableRecipient
Implements IOpenFileDlgVM
Private msg As String
Public Sub New()
End Sub
Public Function OpenFileDlg() As String Implements IOpenFileDlgVM.OpenFileDlg
Dim dialog As FileDialog = New OpenFileDialog()
Try
dialog.Filter = "All Files(*.*)|*.*|RTF Files (*.rtf)|*.rtf"
dialog.FilterIndex = 1
dialog.Title = "Open File"
dialog.DefaultExt = "rtf"
dialog.ShowDialog()
If dialog.FileName = "" Then Exit Function
Dim strExt As String
strExt = System.IO.Path.GetExtension(dialog.FileName)
strExt = strExt.ToUpper()
Dim currentFile As String = dialog.FileName
msg = "OpenFileDlg TEST Msg"
SetStatus("TestingViewModel", msg)
Return currentFile
Catch ex As Exception
IO.File.AppendAllText(sAppPath & "\Log.txt", String.Format("{0}{1}", _
Environment.NewLine, Now.ToString & "; " & ex.ToString()))
Dim MsgCmd As RelayCommand(Of String) = New RelayCommand(Of [String])_
(Function(m) MessageBox.Show("Unexpected error:" & vbNewLine & _
vbNewLine & ex.ToString))
MsgCmd.Execute("")
End Try
End Function
Public Sub SetStatus(r As String, m As String)
Try
Dim s = Messenger.Send(New DialogMessage(m))
Catch ex As Exception
SetStatus("OpenFileDlgVM", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
End Class
Public Class DialogMessage
Public Sub New(status As String)
NewStatus = status
End Sub
Public Property NewStatus As String
End Class
to another viewmodel
, what is only possible if the message
is registered:
Imports Microsoft.Toolkit.Mvvm.Messaging
Public Class TestingViewModel
Inherits ObservableRecipient
Public Sub New()
Try
...
Messenger.Register(Of DialogMessage)(Me, Sub(r, m) r.DialogMessage = m.NewStatus)
...
Protected Overrides Sub Finalize()
Messenger.Unregister(Of DialogMessage)(Me)
MyBase.Finalize()
End Sub
On closing the viewmodel
, we have to unregister the message
.
The message
appears on StatusBar
and the Ribbon
.
PropertyChanged Test
If you edit the upper one on the textbox
es manually, you can see that the lower one‘s content is changed immediately.
This is caused by UpdateSourceTrigger
=PropertyChanged
in the XAML file.
EventTrigger
Requirements: Microsoft.Xaml.Behaviors.Wpf
(NuGet package):
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
...
<Window.DataContext>
<local:TestingViewModel/>
</Window.DataContext>
<b:Interaction.Triggers>
<b:EventTrigger EventName="Closing">
<b:InvokeCommandAction Command="{Binding ExitApp, Mode=OneWay}"/>
</b:EventTrigger>
<b:EventTrigger EventName="Loaded">
<b:InvokeCommandAction Command="{Binding Apploaded, Mode=OneWay}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
This is used for the code to control the QuickAccessToolbar
.
ObservableCollection
It is part of viewmodel
TestingViewModel
and used for the listbox
with Credits / References.
Public Class TestingViewModel
Inherits ObservableRecipient
Implements INotifyPropertyChanged
#Region " fields"
Private _credit As New ObservableCollection(Of Credits)
Private _textData As New TextData
Private msg As String
Private _text As String
Private _dialogMessage As String
Private _OnPropertyChangedTest As String
#End Region
#Region " constructors"
Public Sub New()
Try
MyMainWindow = Windows.Application.Current.MainWindow
Messenger.Register(Of DialogMessage)(Me, Sub(r, m) r.DialogMessage = m.NewStatus)
Messenger.Register(Of StatusMessage)_
(Me, Sub(r, m) r.StatusBarMessage = m.NewStatus)
_credit = New ObservableCollection(Of Credits)() From {
New Credits() With {
.Item = "MVVM Toolkit",
.Note = "Microsoft",
.Link = "https://docs.microsoft.com/en-us/windows/_
communitytoolkit/mvvm/introduction"
},
New Credits() With {
.Item = "MVVMLight",
.Note = "GalaSoft",
.Link = "https://www.codeproject.com/Articles/768427/The-big-MVVM-Template"
},
New Credits() With {
.Item = "ICommand with MVVM pattern",
.Note = "CPOL",
.Link = "https://www.codeproject.com/Articles/863671/
Using-ICommand-with-MVVM-pattern"
},
New Credits() With {
.Item = "C# WPF WYSIWYG HTML Editor - CodeProject",
.Note = "CPOL",
.Link = "https://www.codeproject.com/Tips/870549/_
Csharp-WPF-WYSIWYG-HTML-Editor"
}
}
Dim cmdSearch As New RelayCommand(AddressOf SearchDialog)
SearchDlgCommand = cmdSearch
Dim cmdOFD As New RelayCommand(AddressOf OpenFileDialog)
OpenFileDlgCommand = cmdOFD
Dim cmdSAFD As New RelayCommand(AddressOf SaveAsFileDialog)
SaveAsFileDlgCommand = cmdSAFD
Dim cmdI As New RelayCommand(AddressOf OpenUserInput)
OpenUserInputCommand = cmdI
GetCredits = _credit
SaveXml_Click()
Catch ex As Exception
IO.File.AppendAllText(sAppPath & "\Log.txt", _
String.Format("{0}{1}", Environment.NewLine, _
Now.ToString & "; " & ex.ToString()))
Dim msgBoxService As IMsgBoxService = Ioc.[Default].GetService(Of IMsgBoxService)()
msgBoxService.Show("Unexpected error:" & vbNewLine & _
vbNewLine & ex.ToString,,, Windows.MessageBoxImage.Error)
End Try
End Sub
#End Region
#Region " properties"
Dim _cmdN As New Command(AddressOf New_Click)
Dim _cmdE As New Command(AddressOf Exit_Click)
Dim _cmdD As New Command(AddressOf Print_Click)
Dim _cmdI As New Command(AddressOf Info_Click)
Dim _cmdBG As New Command(AddressOf BackgroundGreenRibbonButton_Click)
Dim _cmdBW As New Command(AddressOf BackgroundWhiteRibbonButton_Click)
Dim _cmdQAT As New Command(AddressOf RestoreQAT_Click)
Dim _cmdMsg As New Command(AddressOf SendMsgRibbonButton_Click)
Dim _cmdErr As New Command(AddressOf GetErrorButton_Click)
Dim _cmdClear As New Command(AddressOf ClearListboxButton_Click)
Dim _cmdLog As New Command(AddressOf ReadLog_Click)
Dim _cmdReadXml As New Command(AddressOf ReadXml_Click)
Dim _cmdSaveXml As New Command(AddressOf SaveXml_Click)
Dim _cmdL As New Command(AddressOf App_Loaded)
Public Property SearchDlgCommand() As ICommand
Public Property OpenUserInputCommand() As ICommand
Public Property RibbonToFormCommand() As ICommand
Public Property OpenFileDlgCommand() As ICommand
Public Property SaveAsFileDlgCommand() As ICommand
Public Property PrintFileDlgCommand() As ICommand
Public Property MyMainWindow As MainWindow
Get
Return _textData.MyMainWindow
End Get
Set(value As MainWindow)
_textData.MyMainWindow = value
If MyMainWindow.RibbonWPF Is Nothing Then MyRibbonWPF = MyMainWindow.RibbonWPF
End Set
End Property
Public Property MyRibbonWPF As Ribbon
Get
Return _textData.MyRibbonWPF
End Get
Set(value As Ribbon)
_textData.MyRibbonWPF = value
End Set
End Property
Public Property ActiveTextBox() As TextBox
Get
Return _textData.ActiveTextBox
End Get
Set(value As TextBox)
_textData.ActiveTextBox = value
OnPropertyChanged("ActiveTextBox")
End Set
End Property
Public Property GetText As String
Get
Return _text
End Get
Set(value As String)
_text = value
_textData.GetText = value
OnPropertyChanged("GetText")
End Set
End Property
Public Property OnPropertyChangedTest As String
Get
Return _OnPropertyChangedTest
End Get
Set(value As String)
_OnPropertyChangedTest = value
OnPropertyChanged("OnPropertyChangedTest")
End Set
End Property
Public Property NotifyTestbox As RibbonTextBox
Get
Return _textData.NotifyTestbox
End Get
Set(value As RibbonTextBox)
_textData.NotifyTestbox = value
OnPropertyChanged("NotifyTestbox")
End Set
End Property
Public Property GetCredits As ObservableCollection(Of Credits)
Get
Return _credit
End Get
Set(value As ObservableCollection(Of Credits))
_credit = value
OnPropertyChanged("GetCredits")
End Set
End Property
Public ReadOnly Property SaveXml As ICommand
Get
Return _cmdSaveXml
End Get
End Property
Public ReadOnly Property ReadXml As ICommand
Get
Return _cmdReadXml
End Get
End Property
Public ReadOnly Property ReadLog As ICommand
Get
Return _cmdLog
End Get
End Property
Public ReadOnly Property SendMsg As ICommand
Get
Return _cmdMsg
End Get
End Property
Public ReadOnly Property GetError As ICommand
Get
Return _cmdErr
End Get
End Property
Public ReadOnly Property ClearListbox As ICommand
Get
Return _cmdClear
End Get
End Property
Public ReadOnly Property GreenBackground() As ICommand
Get
Return _cmdBG
End Get
End Property
Public ReadOnly Property WhiteBackground() As ICommand
Get
Return _cmdBW
End Get
End Property
Public ReadOnly Property RestoreQAT() As ICommand
Get
Return _cmdQAT
End Get
End Property
Public ReadOnly Property Info As ICommand
Get
Return _cmdI
End Get
End Property
Public ReadOnly Property NewFile As ICommand
Get
Return _cmdN
End Get
End Property
Public ReadOnly Property ExitApp As ICommand
Get
Return _cmdE
End Get
End Property
Public ReadOnly Property Apploaded As ICommand
Get
Return _cmdL
End Get
End Property
Public ReadOnly Property Print As ICommand
Get
Return _cmdD
End Get
End Property
#End Region
#Region " Dialogs"
Private Sub SearchDialog()
Dim dialog As ISearchDlgVM = Ioc.[Default].GetService(Of ISearchDlgVM)()
dialog.SearchDlg()
End Sub
Private Sub OpenFileDialog()
Dim dialog As IOpenFileDlgVM = Ioc.[Default].GetService(Of IOpenFileDlgVM)()
Dim sPath As String = dialog.OpenFileDlg()
If Len(sPath) > 1 Then GetText = ReadTextLines(sPath)
End Sub
Private Sub SaveAsFileDialog()
Dim dialog As ISaveAsFileDlgVM = Ioc.[Default].GetService(Of ISaveAsFileDlgVM)()
dialog.SaveAsFileDlg(_textData.GetText)
End Sub
Private Sub OpenUserInput()
Dim dialog As IDialog = Ioc.[Default].GetService(Of IDialog)()
dialog.ShowMyDialog()
End Sub
#End Region
#Region " methods"
Private Sub RestoreQAT_Click()
Try
If MyMainWindow.RibbonWPF IsNot Nothing Then
MyRibbonWPF = MyMainWindow.RibbonWPF
End If
If MyMainWindow.AppCmdNewQAT.IsLoaded = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Add(MyMainWindow.AppCmdNewQAT)
End If
If MyMainWindow.AppCmdOpenQAT.IsLoaded = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Add(MyMainWindow.AppCmdOpenQAT)
End If
If MyMainWindow.AppCmdSaveAsQAT.IsLoaded = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Add(MyMainWindow.AppCmdSaveAsQAT)
End If
If MyMainWindow.AppCmdCloseQAT.IsLoaded = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Add(MyMainWindow.AppCmdCloseQAT)
End If
Catch ex As Exception
IO.File.AppendAllText(sAppPath & "\_Log.txt", _
String.Format("{0}{1}", Environment.NewLine, _
Now.ToString & "; " & ex.ToString()))
Dim msgBoxService As IMsgBoxService = Ioc.[Default].GetService(Of IMsgBoxService)()
msgBoxService.Show("Unexpected error:" & vbNewLine & _
vbNewLine & ex.ToString,,, Windows.MessageBoxImage.Error)
End Try
End Sub
Private Sub ClearListboxButton_Click()
Try
_credit = GetCredits
GetCredits.Clear()
Catch ex As Exception
SetStatus("TestingViewModel", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
Private Sub SaveXml_Click()
Try
Dim xs As New XmlSerializer(GetType(ObservableCollection(Of Credits)))
Using wr As New StreamWriter(sAppPath + "\MyCredits.xml")
xs.Serialize(wr, _credit)
End Using
Catch ex As Exception
SetStatus("TestingViewModel", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
Private Sub ReadXml_Click()
Try
GetCredits.Clear()
Dim xs As New XmlSerializer(GetType(ObservableCollection(Of Credits)))
Using rd As New StreamReader(sAppPath + "\MyCredits.xml")
GetCredits = TryCast(xs.Deserialize(rd), ObservableCollection(Of Credits))
End Using
Catch ex As Exception
SetStatus("TestingViewModel", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
Private Sub ReadLog_Click()
Try
GetText = ReadTextLines(sAppPath & "\Log.txt")
Catch ex As Exception
SetStatus("TestingViewModel", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
Private Sub Info_Click()
msg = "Demo created by Jo_vb.net, v1.0, Feb. 2022, License CPOL."
Dim msgBoxService As IMsgBoxService = Ioc.[Default].GetService(Of IMsgBoxService)()
msgBoxService.Show(vbNewLine & msg, "Info")
End Sub
Private Sub New_Click()
Try
GetText = vbNullString
Catch ex As Exception
IO.File.AppendAllText(sAppPath & "\_Log.txt", _
String.Format("{0}{1}", Environment.NewLine, _
Now.ToString & "; " & ex.ToString()))
Dim msgBoxService As IMsgBoxService = _
Ioc.[Default].GetService(Of IMsgBoxService)()
msgBoxService.Show("Unexpected error:" & vbNewLine & _
vbNewLine & ex.ToString,,, Windows.MessageBoxImage.Error)
End Try
End Sub
Private Sub BackgroundGreenRibbonButton_Click()
If MyMainWindow.RibbonWPF IsNot Nothing Then
MyRibbonWPF = MyMainWindow.RibbonWPF
End If
MyRibbonWPF.Background = New SolidColorBrush(Color.FromRgb(120, 190, 96))
End Sub
Private Sub BackgroundWhiteRibbonButton_Click()
If MyMainWindow.RibbonWPF IsNot Nothing Then
MyRibbonWPF = MyMainWindow.RibbonWPF
End If
MyRibbonWPF.Background = New SolidColorBrush(Color.FromRgb(255, 255, 255))
End Sub
Private Sub Print_Click()
msg = "Print Dialog dummy" & vbNewLine _
& "You could try using" & _
vbNewLine & "https://www.codeproject.com/Tips/829368/A-Simple-RTF-Print-Form"
Dim msgBoxService As IMsgBoxService = Ioc.[Default].GetService(Of IMsgBoxService)()
msgBoxService.Show(vbNewLine & msg, "Info")
End Sub
Private Sub App_Loaded()
Try
If MyMainWindow.RibbonWPF IsNot Nothing Then
MyRibbonWPF = MyMainWindow.RibbonWPF
End If
If My.Settings.AppCmdNewQAT_Visible = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Remove(MyMainWindow.AppCmdNewQAT)
End If
If My.Settings.AppCmdOpenQAT_Visible = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Remove(MyMainWindow.AppCmdOpenQAT)
End If
If My.Settings.AppCmdSaveAsQAT_Visible = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Remove(MyMainWindow.AppCmdSaveAsQAT)
End If
If My.Settings.AppCmdCloseQAT_Visible = False Then
MyRibbonWPF.QuickAccessToolBar.Items.Remove(MyMainWindow.AppCmdCloseQAT)
End If
Catch ex As Exception
IO.File.AppendAllText(sAppPath & "\Log.txt", _
String.Format("{0}{1}", Environment.NewLine, _
Now.ToString & "; " & ex.ToString()))
Dim msgBoxService As IMsgBoxService = _
Ioc.[Default].GetService(Of IMsgBoxService)()
msgBoxService.Show("Unexpected error:" & _
vbNewLine & vbNewLine & ex.ToString,,, Windows.MessageBoxImage.Error)
End Try
End Sub
Private Sub Exit_Click()
Try
With MyMainWindow
If .AppCmdNewQAT.IsLoaded = False Then
My.Settings.AppCmdNewQAT_Visible = False
ElseIf .AppCmdNewQAT.IsLoaded = True Then
My.Settings.AppCmdNewQAT_Visible = True
End If
If .AppCmdOpenQAT.IsLoaded = False Then
My.Settings.AppCmdOpenQAT_Visible = False
ElseIf .AppCmdOpenQAT.IsLoaded = True Then
My.Settings.AppCmdOpenQAT_Visible = True
End If
If .AppCmdSaveAsQAT.IsLoaded = False Then
My.Settings.AppCmdSaveAsQAT_Visible = False
ElseIf .AppCmdSaveAsQAT.IsLoaded = True Then
My.Settings.AppCmdSaveAsQAT_Visible = True
End If
If .AppCmdCloseQAT.IsLoaded = False Then
My.Settings.AppCmdCloseQAT_Visible = False
ElseIf .AppCmdCloseQAT.IsLoaded = True Then
My.Settings.AppCmdCloseQAT_Visible = True
End If
End With
My.Settings.Save()
Catch ex As Exception
IO.File.AppendAllText(sAppPath & "\Log.txt", _
String.Format("{0}{1}", Environment.NewLine, _
Now.ToString & "; " & ex.ToString()))
End Try
Application.Current.Shutdown()
End Sub
Private Sub GetErrorButton_Click()
Try
Ioc.[Default].ConfigureServices(New ServiceCollection().AddSingleton_
(Of IMsgBoxService, MsgBoxService)().AddSingleton(Of IMsgBoxService)_
(New MsgBoxService()).BuildServiceProvider)
Catch ex As Exception
SetStatus("TestingViewModel", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
Private Sub SendMsgRibbonButton_Click()
Try
Dim msg = "Test Msg..."
SetStatus("TestingViewModel", msg)
Catch ex As Exception
SetStatus("TestingViewModel", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
Public Sub SetStatus(ByVal r As String, ByVal m As String)
Try
Messenger.Send(New DialogMessage(m))
Catch ex As Exception
SetStatus("TestingViewModel", ex.ToString)
ErrHandler(ex.ToString)
End Try
End Sub
#End Region
#Region " Dialog Code"
Public Property DialogMessage As String
Get
Return _dialogMessage
End Get
Set(value As String)
If Equals(value, _dialogMessage) Then Return
_dialogMessage = value
GetText = value
OnPropertyChanged("DialogMessage")
End Set
End Property
Private _statusBarMessage As String
Public Property StatusBarMessage As String
Get
Return _statusBarMessage
End Get
Set(ByVal value As String)
If Equals(value, _statusBarMessage) Then Return
_statusBarMessage = value
OnPropertyChanged("StatusBarMessage")
End Set
End Property
Protected Overrides Sub Finalize()
Messenger.Unregister(Of StatusMessage)(Me)
Messenger.Unregister(Of DialogMessage)(Me)
MyBase.Finalize()
End Sub
#End Region
End Class
Public Class StatusMessage
Public Sub New(ByVal status As String)
NewStatus = status
End Sub
Public Property NewStatus As String
End Class
Public Class Credits
Public Property Item As String
Public Property Note As String
Public Property Link As String
End Class
...
Test with the ObservableCollection
Click on Clear Listbox, then delete the credits.
Read XML to Listbox
restores the reference
s.
Another Test: Click on Read Log imports the log file to the textbox.
Conclusion
This is only a rough demo – it is not production ready.
But I think the MVVM Toolkit allows you a variety of extensions.
Final Note
I am very interested in feedback of any kind - problems, suggestions and other.
Credits / Reference
History
- 7th February, 2022 - Initial submission
- 23rd October, 2023 - Version 2.1 - Because
Microsoft.ToolKit.Mvvm
has been deprecated, we now must use this alternate package: CommunityToolkit.Mvvm