From e5b11f80999b13058605350aa0a54910617f7394 Mon Sep 17 00:00:00 2001 From: Konrad Mattheis Date: Mon, 17 Aug 2020 14:56:44 +0200 Subject: [PATCH 1/4] add changes and a small sample --- src/Extensions/LocExtension.cs | 10 +++++----- tests/HelloWorldWPF/MainWindow.xaml | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Extensions/LocExtension.cs b/src/Extensions/LocExtension.cs index 167bc896..e002a803 100644 --- a/src/Extensions/LocExtension.cs +++ b/src/Extensions/LocExtension.cs @@ -68,7 +68,7 @@ internal void OnNotifyPropertyChanged(string property) /// /// Holds the Binding to get the key /// - private Binding _binding; + private BindingBase _binding; /// /// the Name of the cached dynamic generated DependencyProperties @@ -259,10 +259,10 @@ public object ConverterParameter /// Gets or sets the Key that identifies a resource (Assembly:Dictionary:Key) /// [EditorBrowsable(EditorBrowsableState.Never)] - public object ResourceIdentifierKey + public BindingBase ResourceIdentifierKey { - get => _key ?? "(null)"; - set => _key = value.ToString(); + get => _binding; + set => _binding = value; } #endregion @@ -298,7 +298,7 @@ public LocExtension(object key) key = newBinding; } - if (key is Binding binding) + if (key is BindingBase binding) _binding = binding; else Key = key?.ToString(); diff --git a/tests/HelloWorldWPF/MainWindow.xaml b/tests/HelloWorldWPF/MainWindow.xaml index 4c4fba01..002b66b8 100644 --- a/tests/HelloWorldWPF/MainWindow.xaml +++ b/tests/HelloWorldWPF/MainWindow.xaml @@ -74,6 +74,15 @@ + + + + + + + + + From 55f421303e81d8ecda4135b382ffc235116ba317 Mon Sep 17 00:00:00 2001 From: Konrad Mattheis Date: Mon, 17 Aug 2020 15:11:41 +0200 Subject: [PATCH 2/4] add docu --- docs/Localize.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/Localize.md b/docs/Localize.md index ff8b1745..724ce03f 100644 --- a/docs/Localize.md +++ b/docs/Localize.md @@ -53,6 +53,25 @@ the extensions support to add the Binding as Constructor. Because of WPF restric {lex:Loc {Binding Path=Foo}} ``` +or via content + +```xaml + + + +``` + +Multibinding only possible via content please use the following syntax: + +```xaml + + + + + + +``` + This gives you the full flexibility because the Markupextensions is the pure Binding and this supports Converters, StringFormat, ... ### Enums @@ -89,6 +108,6 @@ For translation of complex texts there some value should be in the text like thi >You have selected 10 car(s). -TWe have introduces a StringFormatConverter see [ValueConverters](ValueConverters.md) with automatic using of [smartFormat](https://github.com/axuno/SmartFormat) if this is available. +We have introduced a StringFormatConverter see [ValueConverters](ValueConverters.md) with automatic using of [smartFormat](https://github.com/axuno/SmartFormat) if this is available. A detailed explanation how to use can be found [here](GapText.md). From 2305ee6b19fbca5017362b49b72088d4318a5033 Mon Sep 17 00:00:00 2001 From: Konrad Mattheis Date: Tue, 18 Aug 2020 08:04:01 +0200 Subject: [PATCH 3/4] fix HelloWorld MultiBinding Example because of StringFormatBug --- tests/HelloWorldWPF/MainWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/HelloWorldWPF/MainWindow.xaml b/tests/HelloWorldWPF/MainWindow.xaml index 002b66b8..d451c20b 100644 --- a/tests/HelloWorldWPF/MainWindow.xaml +++ b/tests/HelloWorldWPF/MainWindow.xaml @@ -78,7 +78,7 @@ - + From 0a88120af35ec1ef5e5dff11b0f9d09d15d11bc5 Mon Sep 17 00:00:00 2001 From: Konrad Mattheis Date: Tue, 18 Aug 2020 20:50:34 +0200 Subject: [PATCH 4/4] next level --- src/Deprecated/Engine/LocBinding.cs | 4 +- src/Deprecated/Engine/LocProxy.cs | 6 +-- src/Deprecated/Extensions/Compatibility.cs | 12 ++--- src/Deprecated/Extensions/LocExtension.cs | 23 +++++++++ src/Engine/EnumRun.cs | 6 +-- src/Engine/LocalizeDictionary.cs | 2 +- src/Extensions/LocExtension.cs | 54 ++++++++++++++-------- src/ValueConverters/TranslateConverter.cs | 2 +- tests/HelloWorldWPF/MainWindow.xaml | 10 ++-- 9 files changed, 82 insertions(+), 37 deletions(-) create mode 100644 src/Deprecated/Extensions/LocExtension.cs diff --git a/src/Deprecated/Engine/LocBinding.cs b/src/Deprecated/Engine/LocBinding.cs index 2ce46cb4..058dcbe6 100644 --- a/src/Deprecated/Engine/LocBinding.cs +++ b/src/Deprecated/Engine/LocBinding.cs @@ -45,11 +45,11 @@ public object Source #endregion #region Target LocExtension - private LocExtension _target; + private LocBaseExtension _target; /// /// The target extension. /// - public LocExtension Target + public LocBaseExtension Target { get => _target; set diff --git a/src/Deprecated/Engine/LocProxy.cs b/src/Deprecated/Engine/LocProxy.cs index dd4232fe..3e001ccd 100644 --- a/src/Deprecated/Engine/LocProxy.cs +++ b/src/Deprecated/Engine/LocProxy.cs @@ -22,9 +22,9 @@ namespace WPFLocalizeExtension.Deprecated.Engine public class LocProxy : FrameworkElement { /// - /// Our own instance. + /// Our own instance. /// - private LocExtension _ext; + private LocBaseExtension _ext; #region Source property /// @@ -133,7 +133,7 @@ private static void PropertiesChanged(DependencyObject d, DependencyPropertyChan if (proxy._ext == null) { - proxy._ext = new LocExtension { Key = key }; + proxy._ext = new LocBaseExtension { Key = key }; proxy._ext.SetBinding(proxy, proxy.GetType().GetProperty("Result")); } else diff --git a/src/Deprecated/Extensions/Compatibility.cs b/src/Deprecated/Extensions/Compatibility.cs index 44ae4079..05c667eb 100644 --- a/src/Deprecated/Extensions/Compatibility.cs +++ b/src/Deprecated/Extensions/Compatibility.cs @@ -20,7 +20,7 @@ namespace WPFLocalizeExtension.Deprecated.Extensions /// [Obsolete("LocBrushExtension is deprecated and will be removed in version 4.0, please use lex:Loc instead and see documentation", false)] [MarkupExtensionReturnType(typeof(System.Windows.Media.Brush))] - public class LocBrushExtension : LocExtension + public class LocBrushExtension : LocBaseExtension { /// public LocBrushExtension() @@ -33,7 +33,7 @@ public LocBrushExtension(string key) : base(key) { } /// [Obsolete("LocDoubleExtension is deprecated and will be removed in version 4.0, please use lex:Loc instead and see documentation", false)] [MarkupExtensionReturnType(typeof(double))] - public class LocDoubleExtension : LocExtension + public class LocDoubleExtension : LocBaseExtension { /// public LocDoubleExtension() @@ -46,7 +46,7 @@ public LocDoubleExtension(string key) : base(key) { } /// [MarkupExtensionReturnType(typeof(System.Windows.FlowDirection))] [Obsolete("LocFlowDirectionExtension is deprecated and will be removed in version 4.0, please use lex:Loc instead and see documentation", false)] - public class LocFlowDirectionExtension : LocExtension + public class LocFlowDirectionExtension : LocBaseExtension { /// public LocFlowDirectionExtension() @@ -59,7 +59,7 @@ public LocFlowDirectionExtension(string key) : base(key) { } /// [MarkupExtensionReturnType(typeof(System.Windows.Media.Imaging.BitmapSource))] [Obsolete("LocImageExtension is deprecated and will be removed in version 4.0, please use lex:Loc instead and see documentation", false)] - public class LocImageExtension : LocExtension + public class LocImageExtension : LocBaseExtension { /// public LocImageExtension() @@ -72,7 +72,7 @@ public LocImageExtension(string key) : base(key) { } /// [MarkupExtensionReturnType(typeof(string))] [Obsolete("LocTextExtension is deprecated and will be removed in version 4.0, please use lex:Loc instead and see documentation", false)] - public class LocTextExtension : LocExtension + public class LocTextExtension : LocBaseExtension { #region Constructors /// @@ -323,7 +323,7 @@ protected override string FormatText(string target) /// [MarkupExtensionReturnType(typeof(System.Windows.Thickness))] [Obsolete("LocThicknessExtension is deprecated and will be removed in version 4.0, please use lex:Loc instead and see documentation", false)] - public class LocThicknessExtension : LocExtension + public class LocThicknessExtension : LocBaseExtension { /// public LocThicknessExtension() diff --git a/src/Deprecated/Extensions/LocExtension.cs b/src/Deprecated/Extensions/LocExtension.cs new file mode 100644 index 00000000..2f42f933 --- /dev/null +++ b/src/Deprecated/Extensions/LocExtension.cs @@ -0,0 +1,23 @@ +#region Copyright information +// +// Licensed under Microsoft Public License (Ms-PL) +// https://github.com/XAMLMarkupExtensions/WPFLocalizationExtension/blob/master/LICENSE +// +// Konrad Mattheis +#endregion + +namespace WPFLocalizeExtension.Deprecated.Extensions +{ + using System.Windows.Markup; + + /// > + [ContentProperty("ResourceIdentifierKey")] + public class LocExtension : WPFLocalizeExtension.Extensions.LocBaseExtension + { + /// > + public LocExtension() : base() { } + + /// > + public LocExtension(object key) : base(key) { } + } +} diff --git a/src/Engine/EnumRun.cs b/src/Engine/EnumRun.cs index 99fdb477..11740a2a 100644 --- a/src/Engine/EnumRun.cs +++ b/src/Engine/EnumRun.cs @@ -22,9 +22,9 @@ namespace WPFLocalizeExtension.Engine public class EnumRun : Run { /// - /// Our own instance. + /// Our own instance. /// - private LocExtension _ext; + private LocBaseExtension _ext; #region EnumValue property /// @@ -116,7 +116,7 @@ private static void PropertiesChanged(DependencyObject d, DependencyPropertyChan if (run._ext == null) { - run._ext = new LocExtension { Key = key }; + run._ext = new LocBaseExtension { Key = key }; run._ext.SetBinding(run, run.GetType().GetProperty("Text")); } else diff --git a/src/Engine/LocalizeDictionary.cs b/src/Engine/LocalizeDictionary.cs index d30c13da..052745db 100644 --- a/src/Engine/LocalizeDictionary.cs +++ b/src/Engine/LocalizeDictionary.cs @@ -501,7 +501,7 @@ private void AvailableCulturesCollectionChanged(object sender, NotifyCollectionC /// ~LocalizeDictionary() { - LocExtension.ClearResourceBuffer(); + LocBaseExtension.ClearResourceBuffer(); FELoc.ClearResourceBuffer(); BLoc.ClearResourceBuffer(); } diff --git a/src/Extensions/LocExtension.cs b/src/Extensions/LocExtension.cs index e002a803..c1c7664b 100644 --- a/src/Extensions/LocExtension.cs +++ b/src/Extensions/LocExtension.cs @@ -24,6 +24,7 @@ namespace WPFLocalizeExtension.Extensions using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Media.Media3D; + using WPFLocalizeExtension.Deprecated.Engine; using WPFLocalizeExtension.Engine; using WPFLocalizeExtension.Providers; using WPFLocalizeExtension.TypeConverters; @@ -33,8 +34,7 @@ namespace WPFLocalizeExtension.Extensions /// /// A generic localization extension. /// - [ContentProperty("ResourceIdentifierKey")] - public class LocExtension : NestedMarkupExtension, INotifyPropertyChanged, IDictionaryEventListener, IDisposable + public abstract class LocBaseExtension : NestedMarkupExtension, INotifyPropertyChanged, IDictionaryEventListener, IDisposable { #region PropertyChanged Logic /// @@ -150,9 +150,9 @@ internal static void SafeRemoveItemFromResourceBuffer(string key) /// The target property name. /// The index in the property (if applicable). /// The bound extension or null, if not available. - public static LocExtension GetBoundExtension(object target, string property, int propertyIndex = -1) + public static LocBaseExtension GetBoundExtension(object target, string property, int propertyIndex = -1) { - foreach (var ext in LocalizeDictionary.DictionaryEvent.EnumerateListeners()) + foreach (var ext in LocalizeDictionary.DictionaryEvent.EnumerateListeners()) { var ep = ext._lastEndpoint; @@ -200,7 +200,7 @@ private static string GetPropertyName(object property) #region Properties /// - /// Gets or sets the Key to a .resx object + /// Gets or sets the Key that identifies a resource (Assembly:Dictionary:Key) /// public string Key { @@ -217,6 +217,24 @@ public string Key } } + /// + /// Gets or sets the Binding that delivers the Key that identifies a resource (Assembly:Dictionary:Key) + /// + public BindingBase KeyBinding + { + get => _binding; + set + { + if (_binding != value) + { + _binding = value; + UpdateNewValue(); + + OnNotifyPropertyChanged(nameof(Key)); + } + } + } + /// /// Gets or sets the custom value converter. /// @@ -259,18 +277,18 @@ public object ConverterParameter /// Gets or sets the Key that identifies a resource (Assembly:Dictionary:Key) /// [EditorBrowsable(EditorBrowsableState.Never)] - public BindingBase ResourceIdentifierKey + public object ResourceIdentifierKey { - get => _binding; - set => _binding = value; + get => _key ?? "(null)"; + set => _key = value.ToString(); } #endregion #region Constructors & Dispose /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public LocExtension() + public LocBaseExtension() { // Register this extension as an event listener on the first target. OnFirstTarget = () => @@ -280,10 +298,10 @@ public LocExtension() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The resource identifier. - public LocExtension(object key) + public LocBaseExtension(object key) : this() { if (key is TemplateBindingExpression tbe) @@ -317,7 +335,7 @@ public LocExtension(object key) /// /// The finalizer. /// - ~LocExtension() + ~LocBaseExtension() { Dispose(); } @@ -476,13 +494,13 @@ public override object FormatOutput(TargetInfo endPoint, TargetInfo info) { MethodInfo mi = typeof(DependencyProperty).GetMethod("FromName", BindingFlags.Static | BindingFlags.NonPublic); - cacheDPThis = mi.Invoke(null, new object[] { name, typeof(LocExtension) }) as DependencyProperty - ?? DependencyProperty.RegisterAttached(name, typeof(NestedMarkupExtension), typeof(LocExtension), + cacheDPThis = mi.Invoke(null, new object[] { name, typeof(LocBaseExtension) }) as DependencyProperty + ?? DependencyProperty.RegisterAttached(name, typeof(NestedMarkupExtension), typeof(LocBaseExtension), new PropertyMetadata(null)); - cacheDPKey = mi.Invoke(null, new object[] { name + ".Key", typeof(LocExtension) }) as DependencyProperty - ?? DependencyProperty.RegisterAttached(name + ".Key", typeof(string), typeof(LocExtension), - new PropertyMetadata("", (d, e) => { (d?.GetValue(cacheDPThis) as LocExtension)?.UpdateNewValue(); })); + cacheDPKey = mi.Invoke(null, new object[] { name + ".Key", typeof(LocBaseExtension) }) as DependencyProperty + ?? DependencyProperty.RegisterAttached(name + ".Key", typeof(string), typeof(LocBaseExtension), + new PropertyMetadata("", (d, e) => { (d?.GetValue(cacheDPThis) as LocBaseExtension)?.UpdateNewValue(); })); cacheDPName = name; } diff --git a/src/ValueConverters/TranslateConverter.cs b/src/ValueConverters/TranslateConverter.cs index 15fb5fb8..e7ad1659 100644 --- a/src/ValueConverters/TranslateConverter.cs +++ b/src/ValueConverters/TranslateConverter.cs @@ -54,7 +54,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn culture = LocalizeDictionary.Instance.SpecificCulture; var _key = value.ToString(); - var result = LocExtension.GetLocalizedValue(targetType, _key, culture, null); + var result = LocBaseExtension.GetLocalizedValue(targetType, _key, culture, null); if (result == null) { diff --git a/tests/HelloWorldWPF/MainWindow.xaml b/tests/HelloWorldWPF/MainWindow.xaml index d451c20b..45f7c4cb 100644 --- a/tests/HelloWorldWPF/MainWindow.xaml +++ b/tests/HelloWorldWPF/MainWindow.xaml @@ -8,6 +8,7 @@ xmlns:local="clr-namespace:HalloWeltWPF" d:DataContext="{d:DesignInstance Type=local:TestVM, IsDesignTimeCreatable=True}" mc:Ignorable="d" + lex:LocalizeDictionary.DesignCulture="en" lex:LocalizeDictionary.IncludeInvariantCulture="False" lex:ResxLocalizationProvider.DefaultAssembly="HelloWorldWPF" @@ -77,9 +78,12 @@ - - - + en + + +