Skip to content

Commit

Permalink
Added events ViewModelAttached, ViewModelPropertyChanged and ViewMode…
Browse files Browse the repository at this point in the history
…lDetached on MvvmWindow and MvvmUserControl
  • Loading branch information
RolandKoenig committed Jan 21, 2024
1 parent 7544845 commit 5dbc56f
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<!-- Commn configuration-->
<PropertyGroup>
<Nullable>enable</Nullable>
<LangVersion>11.0</LangVersion>
<LangVersion>12</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<NoWarn>1591,1712</NoWarn>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@

namespace RolandK.AvaloniaExtensions.Mvvm;

public class CloseWindowRequestEventArgs
public class CloseWindowRequestEventArgs(object? dialogResult) : EventArgs
{
public object? DialogResult { get; }

public CloseWindowRequestEventArgs(object? dialogResult)
{
this.DialogResult = dialogResult;
}
public object? DialogResult { get; } = dialogResult;
}
52 changes: 51 additions & 1 deletion src/RolandK.AvaloniaExtensions/Mvvm/Controls/MvvmUserControl.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Avalonia.Controls;
using Avalonia.LogicalTree;
using RolandK.AvaloniaExtensions.ViewServices;
Expand All @@ -14,6 +15,12 @@ public class MvvmUserControl : UserControl, IViewServiceHost
private ViewServiceContainer _viewServiceContainer;
private Type? _viewFor;

public event EventHandler<ViewModelAttachedEventArgs>? ViewModelAttached;

public event EventHandler<ViewModelPropertyChangedEventArgs>? ViewModelPropertyChanged;

public event EventHandler<ViewModelDetachedEventArgs>? ViewModelDetached;

public Type? ViewFor
{
get => _viewFor;
Expand Down Expand Up @@ -76,6 +83,21 @@ protected override void OnDataContextChanged(EventArgs e)

this.TryAttachToDataContext();
}

protected virtual void OnViewModelPropertyChanged(ViewModelPropertyChangedEventArgs args)
{
this.ViewModelPropertyChanged?.Invoke(this, args);
}

protected virtual void OnViewModelAttached(ViewModelAttachedEventArgs args)
{
this.ViewModelAttached?.Invoke(this, args);
}

protected virtual void OnViewModelDetached(ViewModelDetachedEventArgs args)
{
this.ViewModelDetached?.Invoke(this, args);
}

private void OnViewForChanged()
{
Expand All @@ -101,8 +123,14 @@ private void TryAttachToDataContext()
$"is already attached to a view of type {dataContextAttachable.AssociatedView.GetType().FullName}");
}

var dataContextPropertyChanged = dataContextAttachable as INotifyPropertyChanged;

dataContextAttachable.ViewServiceRequest += this.OnDataContextAttachable_ViewServiceRequest;
dataContextAttachable.CloseWindowRequest += this.OnDataContextAttachable_CloseWindowRequest;
if (dataContextPropertyChanged != null)
{
dataContextPropertyChanged.PropertyChanged += this.OnDataContextAttachable_PropertyChanged;
}
try
{
dataContextAttachable.AssociatedView = this;
Expand All @@ -111,19 +139,32 @@ private void TryAttachToDataContext()
{
dataContextAttachable.ViewServiceRequest -= this.OnDataContextAttachable_ViewServiceRequest;
dataContextAttachable.CloseWindowRequest -= this.OnDataContextAttachable_CloseWindowRequest;
if (dataContextPropertyChanged != null)
{
dataContextPropertyChanged.PropertyChanged -= this.OnDataContextAttachable_PropertyChanged;
}
throw;
}

_currentlyAttachedViewModel = dataContextAttachable;
this.OnViewModelAttached(new ViewModelAttachedEventArgs(dataContextAttachable));
}
}

private void DetachFromDataContext()
{
if (_currentlyAttachedViewModel != null)
{
_currentlyAttachedViewModel.AssociatedView = null;
_currentlyAttachedViewModel.ViewServiceRequest -= this.OnDataContextAttachable_ViewServiceRequest;
_currentlyAttachedViewModel.CloseWindowRequest -= this.OnDataContextAttachable_CloseWindowRequest;
_currentlyAttachedViewModel.AssociatedView = null;

if (_currentlyAttachedViewModel is INotifyPropertyChanged dataContextPropertyChanged)
{
dataContextPropertyChanged.PropertyChanged -= this.OnDataContextAttachable_PropertyChanged;
}

this.OnViewModelDetached(new ViewModelDetachedEventArgs(_currentlyAttachedViewModel));
}
_currentlyAttachedViewModel = null;
}
Expand All @@ -134,6 +175,15 @@ private void DetachFromDataContext()
return DefaultViewServices.TryGetDefaultViewService(this, viewServiceType);
}

private void OnDataContextAttachable_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_currentlyAttachedViewModel == null) { return; }

this.OnViewModelPropertyChanged(new ViewModelPropertyChangedEventArgs(
_currentlyAttachedViewModel,
e.PropertyName));
}

private void OnDataContextAttachable_ViewServiceRequest(object? sender, ViewServiceRequestEventArgs e)
{
var viewService = this.TryFindViewService(e.ViewServiceType);
Expand Down
50 changes: 50 additions & 0 deletions src/RolandK.AvaloniaExtensions/Mvvm/Controls/MvvmWindow.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel;
using Avalonia.Controls;
using Avalonia.Platform;
using RolandK.AvaloniaExtensions.ViewServices;
Expand All @@ -12,6 +13,12 @@ public class MvvmWindow : Window, IViewServiceHost
private ViewServiceContainer _viewServiceContainer;
private Type? _viewFor;

public event EventHandler<ViewModelAttachedEventArgs>? ViewModelAttached;

public event EventHandler<ViewModelPropertyChangedEventArgs>? ViewModelPropertyChanged;

public event EventHandler<ViewModelDetachedEventArgs>? ViewModelDetached;

public Type? ViewFor
{
get => _viewFor;
Expand Down Expand Up @@ -76,6 +83,21 @@ protected override void OnDataContextChanged(EventArgs e)
}
}

protected virtual void OnViewModelPropertyChanged(ViewModelPropertyChangedEventArgs args)
{
this.ViewModelPropertyChanged?.Invoke(this, args);
}

protected virtual void OnViewModelAttached(ViewModelAttachedEventArgs args)
{
this.ViewModelAttached?.Invoke(this, args);
}

protected virtual void OnViewModelDetached(ViewModelDetachedEventArgs args)
{
this.ViewModelDetached?.Invoke(this, args);
}

private void OnViewForChanged()
{
if (!_isOpened) { return; }
Expand All @@ -100,8 +122,15 @@ private void TryAttachToDataContext()
$"is already attached to a view of type {dataContextAttachable.AssociatedView.GetType().FullName}");
}

var dataContextPropertyChanged = dataContextAttachable as INotifyPropertyChanged;

dataContextAttachable.ViewServiceRequest += this.OnDataContextAttachable_ViewServiceRequest;
dataContextAttachable.CloseWindowRequest += this.OnDataContextAttachable_CloseWindowRequest;
if (dataContextPropertyChanged != null)
{
dataContextPropertyChanged.PropertyChanged += this.OnDataContextAttachable_PropertyChanged;
}

try
{
dataContextAttachable.AssociatedView = this;
Expand All @@ -110,9 +139,14 @@ private void TryAttachToDataContext()
{
dataContextAttachable.ViewServiceRequest -= this.OnDataContextAttachable_ViewServiceRequest;
dataContextAttachable.CloseWindowRequest -= this.OnDataContextAttachable_CloseWindowRequest;
if (dataContextPropertyChanged != null)
{
dataContextPropertyChanged.PropertyChanged -= this.OnDataContextAttachable_PropertyChanged;
}
throw;
}
_currentlyAttachedViewModel = dataContextAttachable;
this.OnViewModelAttached(new ViewModelAttachedEventArgs(dataContextAttachable));
}
}

Expand All @@ -123,6 +157,13 @@ private void DetachFromDataContext()
_currentlyAttachedViewModel.AssociatedView = null;
_currentlyAttachedViewModel.CloseWindowRequest -= this.OnDataContextAttachable_CloseWindowRequest;
_currentlyAttachedViewModel.ViewServiceRequest -= this.OnDataContextAttachable_ViewServiceRequest;

if (_currentlyAttachedViewModel is INotifyPropertyChanged dataContextPropertyChanged)
{
dataContextPropertyChanged.PropertyChanged -= this.OnDataContextAttachable_PropertyChanged;
}

this.OnViewModelDetached(new ViewModelDetachedEventArgs(_currentlyAttachedViewModel));
}
_currentlyAttachedViewModel = null;
}
Expand All @@ -133,6 +174,15 @@ private void DetachFromDataContext()
return DefaultViewServices.TryGetDefaultViewService(this, viewServiceType);
}

private void OnDataContextAttachable_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_currentlyAttachedViewModel == null) { return; }

this.OnViewModelPropertyChanged(new ViewModelPropertyChangedEventArgs(
_currentlyAttachedViewModel,
e.PropertyName));
}

private void OnDataContextAttachable_ViewServiceRequest(object? sender, ViewServiceRequestEventArgs e)
{
var viewService = this.TryFindViewService(e.ViewServiceType);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace RolandK.AvaloniaExtensions.Mvvm;

public class ViewModelAttachedEventArgs(IAttachableViewModel viewModel) : EventArgs
{
public IAttachableViewModel ViewModel { get; } = viewModel;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace RolandK.AvaloniaExtensions.Mvvm;

public class ViewModelDetachedEventArgs(IAttachableViewModel viewModel) : EventArgs
{
public IAttachableViewModel ViewModel { get; } = viewModel;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace RolandK.AvaloniaExtensions.Mvvm;

public class ViewModelPropertyChangedEventArgs(IAttachableViewModel viewModel, string propertyName) : EventArgs
{
public IAttachableViewModel ViewModel { get; } = viewModel;

public string PropertyName { get; } = propertyName;
}

0 comments on commit 5dbc56f

Please sign in to comment.