Add project files.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
using TheXamlGuy.UI.WPF;
|
||||
|
||||
namespace TheXamlGuy.Framework.WPF
|
||||
{
|
||||
[MarkupExtensionReturnType(typeof(Control))]
|
||||
public class RouteExtension : MarkupExtension
|
||||
{
|
||||
private static readonly DependencyProperty RouteProperty =
|
||||
DependencyProperty.RegisterAttached("Route",
|
||||
typeof(IRoute), typeof(RouteExtension));
|
||||
|
||||
private readonly string name;
|
||||
private readonly Binding routeBinding;
|
||||
private PropertyChangedRevoker? dataContextPropertyChangedRevoker;
|
||||
|
||||
public RouteExtension(object route, string name)
|
||||
{
|
||||
routeBinding = route.ToBinding();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private bool TryGetDataContext(DependencyObject target, out object dataContext)
|
||||
{
|
||||
dataContext = target.GetValue(FrameworkElement.DataContextProperty) ?? target.GetValue(FrameworkContentElement.DataContextProperty);
|
||||
return dataContext is not null;
|
||||
}
|
||||
|
||||
public override object? ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (dataContextPropertyChangedRevoker is not null)
|
||||
{
|
||||
dataContextPropertyChangedRevoker.Dispose();
|
||||
dataContextPropertyChangedRevoker = null;
|
||||
}
|
||||
|
||||
if (serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget target)
|
||||
{
|
||||
if (target.TargetObject is FrameworkElement frameworkElement)
|
||||
{
|
||||
if (!TryGetDataContext(frameworkElement, out object dataContext))
|
||||
{
|
||||
dataContextPropertyChangedRevoker = new PropertyChangedRevoker(frameworkElement, FrameworkElement.DataContextProperty, OnDataContextPropertyChangedChanged);
|
||||
void OnDataContextPropertyChangedChanged(object sender, DependencyPropertyChangedEventArgs _)
|
||||
{
|
||||
if (TryGetDataContext(frameworkElement, out dataContext))
|
||||
{
|
||||
frameworkElement.Loaded -= HandleLoaded;
|
||||
|
||||
BindingOperations.SetBinding(frameworkElement, RouteProperty, routeBinding);
|
||||
if (frameworkElement?.GetValue(RouteProperty) is IRoute route)
|
||||
{
|
||||
route.AddRoute(name, frameworkElement);
|
||||
BindingOperations.ClearBinding(frameworkElement, RouteProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleLoaded(object sender, RoutedEventArgs args)
|
||||
{
|
||||
frameworkElement.Loaded -= HandleLoaded;
|
||||
if (TryGetDataContext(frameworkElement, out dataContext))
|
||||
{
|
||||
BindingOperations.SetBinding(frameworkElement, RouteProperty, routeBinding);
|
||||
if (frameworkElement?.GetValue(RouteProperty) is IRoute route)
|
||||
{
|
||||
route.AddRoute(name, frameworkElement);
|
||||
BindingOperations.ClearBinding(frameworkElement, RouteProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frameworkElement.Loaded += HandleLoaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
BindingOperations.SetBinding(frameworkElement, RouteProperty, routeBinding);
|
||||
if (frameworkElement?.GetValue(RouteProperty) is IRoute route)
|
||||
{
|
||||
route.AddRoute(name, frameworkElement);
|
||||
BindingOperations.ClearBinding(frameworkElement, RouteProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user