It looks a lot closer to what I do, though I do something different than using nameof(class) in order to not have to worry about naming errors that doesn't rely on intellisense. This is an example of one of my viewmodels that I've written:
public class ConfigurationViewModel: INotifyPropertyChanged
{
public ConfigurationSettingsModel Model { get; set; }
public ConfigurationViewModel(ConfigurationSettingsModel model)
{
this.Model = model;
// create commands
this.OkCommand = new RelayCommand(param => this.OkCommandExecute(), param => this.CanOk);
this.CancelCommand = new RelayCommand(param => this.CancelCommandExecute(), param => this.CanCancel);
}
#region Commands
#region OkCommand
public ICommand OkCommand
{
get;
internal set;
}
private bool CanOk
{
get
{
return this.ValidateSettings();
}
}
public void OkCommandExecute()
{
this.Model.SaveSettings();
this.DialogResult = true;
}
#endregion
#region CancelCommand
public ICommand CancelCommand
{
get;
internal set;
}
private bool CanCancel
{
get
{
return true;
}
}
public void CancelCommandExecute()
{
this.Model.RefreshData();
this.DialogResult = false;
}
#endregion
#endregion
#region Observable Properties
private bool? _DialogResult = null;
public bool? DialogResult
{
get
{
return this._DialogResult;
}
set
{
if (value != this._DialogResult)
{
this._DialogResult = value;
this.NotifyPropertyChanged(() => this.DialogResult);
}
}
}
#endregion
#region Helper Methods
private bool ValidateSettings()
{
return true;
}
#endregion
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
protected void NotifyPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
{
var lambda = (LambdaExpression)property;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else
memberExpression = (MemberExpression)lambda.Body;
this.OnPropertyChanged(memberExpression.Member.Name);
}
#endregion
But I will say that guy does seem to break it down a lot better than the first video that I saw, and I think his methods would be worth following from what I saw.
I didn't notice what he did for a bootstrapper, but I use the simple expident of making use of a couple of properties of the app.xaml.
In the app.xaml, I set it up like so:
<Application x:Class="ApplicationName.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup"
SessionEnding="App_SessionEnding">
<Application.Resources>
</Application.Resources>
</Application>
Normally that startup is set to the first form- but this gives me a chance to go into the bootstrapper.
Then in the app.xaml.cs, I set up those two events. The startup event is below.
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RequestClose = false;
this.SettingsConfiguration = this.GetConfiguration();
this.SettingsModel = new ConfigurationSettingsModel(this.SettingsConfiguration);
this.ViewModel = new MainViewModel(this.SettingsModel);
this.View = new MainView(this.ViewModel);
this.View.Closing += this.OnClosing;
this.ViewModel.RequestConfigurationDialog += new EventHandler(ViewModel_RequestConfigurationDialog);
this.ViewModel.RequestShowAboutDialog += new EventHandler(ViewModel_RequestShowAboutDialog);
// When the ViewModel asks to be closed, it closes the window via attached behaviour.
// We use this event to shut down the remaining parts of the application
this.ViewModel.RequestClose += delegate
{
// Make sure close down event is processed only once
if (this.RequestClose == false)
{
this.RequestClose = true;
// Save session data and close application
this.OnClosed(this.ViewModel, this.View);
}
};
this.InitializeViewCommandBindings(); // Initialize RoutedCommand bindings
this.View.Show();
}
private void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
e.Cancel = this.OnSessionEnding();
}
private bool OnSessionEnding()
{
if (this.ViewModel != null)
{
if (this.ViewModel.CanClose == false)
{
MessageBox.Show("Application is not ready to exit.",
"Cannot exit application", MessageBoxButton.OK);
return !this.ViewModel.CanClose; // Cancel close down request if ViewModel is not ready, yet
}
return !this.ViewModel.CanClose; // Cancel close down request if ViewModel is not ready, yet
}
return true;
}
private void OnClosed(MainViewModel viewModel, MainView view)
{
// Persist data here
this.SettingsModel.SaveSettings();
Application.Current.Shutdown();
}
There's a bit more to it- but I thought that knowing how the bootstrapper is set up and an alternate way to hook up the INotifyPropertyChanged might be of benefit to perhaps encapsulate in what he refers to in the video.