使い方
<TextBlock Text="{sample:ResourceBinding Path=ResourceName}" />
実装
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace Sample
{
<summary>
</summary>
public class ResourceBinding : MarkupExtension
{
<summary>
</summary>
<param name="obj"></param>
<returns></returns>
public static object GetResourceReference(DependencyObject obj)
{
return obj.GetValue(ResourceReferenceProperty);
}
<summary>
</summary>
<param name="obj"></param>
<param name="value"></param>
public static void SetResourceReference(DependencyObject obj, object value)
{
obj.SetValue(ResourceReferenceProperty, value);
}
<summary>
</summary>
public static readonly DependencyProperty ResourceReferenceProperty =
DependencyProperty.RegisterAttached(
"ResourceReference",
typeof(object),
typeof(ResourceBinding),
new PropertyMetadata(null));
<summary>
</summary>
public object Source { get; set; }
<summary>
</summary>
public PropertyPath Path { get; set; }
<summary>
</summary>
[DefaultValue(null)]
public string XPath { get; set; }
<summary>
</summary>
[DefaultValue(BindingMode.Default)]
public BindingMode Mode { get; set; }
<summary>
</summary>
[DefaultValue(UpdateSourceTrigger.Default)]
public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
<summary>
</summary>
[DefaultValue(null)]
public RelativeSource RelativeSource { get; set; }
<summary>
</summary>
[DefaultValue(null)]
public string ElementName { get; set; }
<summary>
<see cref="ResourceBinding"/>
</summary>
public ResourceBinding()
{
}
<summary>
<see cref="ResourceBinding"/>
</summary>
<param name="path"></param>
public ResourceBinding(string path)
{
Path = new PropertyPath(path);
}
<summary>
</summary>
<param name="serviceProvider"></param>
public override object ProvideValue(IServiceProvider serviceProvider)
{
var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
if (provideValueTarget == null)
{
return null;
}
if (provideValueTarget.TargetObject.GetType().FullName == "System.Windows.SharedDp")
{
return this;
}
var targetObject = provideValueTarget.TargetObject as FrameworkElement;
var targetProperty = provideValueTarget.TargetProperty as DependencyProperty;
if (targetObject == null || targetProperty == null)
{
return null;
}
var binding = new Binding
{
Path = Path,
XPath = XPath,
Mode = Mode,
UpdateSourceTrigger = UpdateSourceTrigger
};
if (RelativeSource != null)
{
binding.RelativeSource = RelativeSource;
}
if (ElementName != null)
{
binding.ElementName = ElementName;
}
if (Source != null)
{
binding.Source = Source;
}
var expr = BindingOperations.SetBinding(targetObject, ResourceReferenceProperty, binding);
var descriptor = DependencyPropertyDescriptor.FromProperty(ResourceReferenceProperty, targetObject.GetType());
descriptor.AddValueChanged(targetObject, (s, e) =>
{
var changeKey = targetObject.GetValue(ResourceReferenceProperty);
var newDre = new DynamicResourceExtension(changeKey);
targetObject.SetValue(targetProperty, newDre.ProvideValue(new ServiceValueProvider()));
});
expr.UpdateSource();
var key = targetObject.GetValue(ResourceReferenceProperty);
if (key != null)
{
var dre = new DynamicResourceExtension(key);
return dre.ProvideValue(new ServiceValueProvider());
}
return null;
}
<summary>
</summary>
<returns></returns>
private Binding CreateBinding()
{
var baseBinding = new Binding
{
Path = Path,
XPath = XPath,
Mode = Mode,
UpdateSourceTrigger = UpdateSourceTrigger
};
if (RelativeSource != null)
{
baseBinding.RelativeSource = RelativeSource;
}
if (ElementName != null)
{
baseBinding.ElementName = ElementName;
}
if (Source != null)
{
baseBinding.Source = Source;
}
return baseBinding;
}
}
<summary>
</summary>
public class ServiceValueProvider : IServiceProvider, IProvideValueTarget
{
public object TargetObject { get; private set; }
public object TargetProperty { get; private set; }
public object GetService(Type serviceType)
{
if (serviceType == typeof(IProvideValueTarget))
{
return this;
}
return null;
}
internal void SetData(object targetObject, object targetProperty)
{
TargetObject = targetObject;
TargetProperty = targetProperty;
}
}
}