Skip to content

Instantly share code, notes, and snippets.

@bizouarn
Last active February 28, 2023 13:16
Show Gist options
  • Save bizouarn/e29179909994762b243a09fa51f86002 to your computer and use it in GitHub Desktop.
Save bizouarn/e29179909994762b243a09fa51f86002 to your computer and use it in GitHub Desktop.
Exemple de MarkupExtension WPF avec rafraîchissement
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
[MarkupExtensionReturnType(typeof(string))]
public class TraductionExtension : MarkupExtension
{
private static readonly HashSet<EventHandler> UiCultureChangedHandlers = new();
private WeakReference _targetObjectRef;
private object _targetProperty;
public TraductionExtension(string path)
{
Path = path;
}
[ConstructorArgument("path")]
public string Path { get; }
public sealed override object ProvideValue(IServiceProvider serviceProvider)
{
var target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
// Si le contexte est statique (exemple : DataTemplate), nous retournons `this` afin que la liaison soit évaluée dynamiquement.
if (target != null && target.TargetObject.GetType().FullName == "System.Windows.SharedDp")
return this;
return ProvideValueInternal(serviceProvider);
}
private object ProvideValueInternal(IServiceProvider serviceProvider)
{
if (serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget
{
TargetObject: { }, TargetProperty: { }
} target)
{
_targetObjectRef = new WeakReference(target.TargetObject);
_targetProperty = target.TargetProperty;
UiCultureChanged += TraductionExtension_UICultureChanged;
}
var traduction = GetTraduction();
// Si la traduction est trouvé avec Path
if (traduction != Path) return traduction;
// Sinon créer un binding
SetBinding();
return Path;
}
private string GetTraduction()
{
var traduction = "";
// TODO : Récupère la traduction
// Si la traduction n'est pas trouvée (renvoie Path)
return !string.IsNullOrEmpty(traduction) ? traduction : Path;
}
private void TraductionExtension_UICultureChanged(object sender, EventArgs e)
{
Refresh();
}
public static event EventHandler UiCultureChanged
{
add => UiCultureChangedHandlers.Add(value);
remove => UiCultureChangedHandlers.Remove(value);
}
public static void OnUICultureChanged()
{
foreach (var handler in UiCultureChangedHandlers) handler(typeof(TraductionExtension), EventArgs.Empty);
}
private void Refresh()
{
if (!_targetObjectRef.IsAlive) // Si la référence n'est plus active
{
// Suppression du handler
UiCultureChanged -= TraductionExtension_UICultureChanged;
return;
}
var value = GetTraduction();
if (_targetProperty is DependencyProperty dp)
{
var obj = _targetObjectRef.Target as DependencyObject;
if (value.Equals(Path)) // Si la traduction n'est pas trouvé avec Path
SetBinding(); // Créer un binding
else
obj.SetValue(dp, value); // Sinon applique la traduction à la propriété
}
else
{
var obj = _targetObjectRef.Target;
var prop = _targetProperty as PropertyInfo;
prop.SetValue(obj, value, null);
}
}
private void SetBinding()
{
var obj = _targetObjectRef.Target as DependencyObject;
var prop = _targetProperty as DependencyProperty;
var frameworkElement = _targetObjectRef.Target as FrameworkElement;
Binding binding = new Binding();
binding.Source = frameworkElement.DataContext;
// TODO : Modifier Binding attr
BindingOperations.SetBinding(obj, prop, binding);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment