Last active
February 28, 2023 13:16
-
-
Save bizouarn/e29179909994762b243a09fa51f86002 to your computer and use it in GitHub Desktop.
Exemple de MarkupExtension WPF avec rafraîchissement
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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