The question is really good.
So just will not work. In order to bind to the data from the VM, and so that it can be updated, you must put a key for the DynamicResource
in the VM. (This is how I understand you did.)
Now you need to bind on this key. There are several ways, the general meaning of which is to tie the key somewhere, and to change it, change the Dynamic Resource binding.
For example, you can. Let's set auxiliary class:
static class ResourceKeyBinding { // стандартное attached property ResourceKey public static object GetResourceKey(DependencyObject obj) => obj.GetValue(ResourceKeyProperty); public static void SetResourceKey(DependencyObject obj, object value) => obj.SetValue(ResourceKeyProperty, value); public static readonly DependencyProperty ResourceKeyProperty = DependencyProperty.RegisterAttached( "ResourceKey", typeof(object), typeof(ResourceKeyBinding), // callback при изменении значения ResourceKey new PropertyMetadata(OnResourceKeyChanged)); // стандартное attached property ResourceValue public static object GetResourceValue(DependencyObject obj) => obj.GetValue(ResourceValueProperty); public static void SetResourceValue(DependencyObject obj, object value) => obj.SetValue(ResourceValueProperty, value); public static readonly DependencyProperty ResourceValueProperty = DependencyProperty.RegisterAttached( "ResourceValue", typeof(object), typeof(ResourceKeyBinding)); // это будет вызвано при изменении значения ResourceKey: static void OnResourceKeyChanged( DependencyObject self, DependencyPropertyChangedEventArgs e) { // SetResourceReference устанавливает dynamic resource-привязку ((FrameworkElement)self).SetResourceReference(ResourceValueProperty, e.NewValue); } }
Use this:
<MenuItem Command="{Binding Path=Command}" local:ResourceKeyBinding.ResourceKey="{Binding Path=DisplayName}" Header="{Binding Path=(local:ResourceKeyBinding.ResourceValue), RelativeSource={RelativeSource Self}}" />
Explanation: We added two attached property: ResourceKeyBinding.ResourceKey
and ResourceKeyBinding.ResourceValue
. First tied via Binding
to VM. On changing the first to the second, set the DynamicResource
with the key equal to the current value. Now Header
bound to this second attached property via Binding
.
In principle, it would be possible to simplify the code, costing only one attached property:
static class ResourceKeyBinding { // standard attached property ResourceKey public static object GetResourceKey(DependencyObject obj) => obj.GetValue(ResourceKeyProperty); public static void SetResourceKey(DependencyObject obj, object value) => obj.SetValue(ResourceKeyProperty, value); public static readonly DependencyProperty ResourceKeyProperty = DependencyProperty.RegisterAttached( "ResourceKey", typeof(object), typeof(ResourceKeyBinding), new PropertyMetadata((d, e) => ((FrameworkElement)d).SetResourceReference( MenuItem.HeaderProperty, e.NewValue))); }
and using just like
<MenuItem Command="{Binding Path=Command}" local:ResourceKeyBinding.ResourceKey="{Binding Path=DisplayName}"/>
But such a solution would only work with MenuItem
, and you probably need to localize other types of items.