Вы на правильном пути. Использование прикрепленного свойства - путь.
Самое простое решение
Если вы хотите написать код для каждого унаследованного свойства (их не так много), это может быть намного проще:
<Setter Property="my:OnlyIfSet.FontWeight" Value="{Binding XPath=@font-weight}"/>
с кодом
public class OnlyIfSet : DependencyObject
{
public static FontWeight GetFontWeight(DependencyObject obj) { return (FontWeight)obj.GetValue(FontWeightProperty); }
public static void SetFontWeight(DependencyObject obj, FontWeight value) { obj.SetValue(FontWeightProperty, value); }
public static readonly DependencyProperty FontWeightProperty = DependencyProperty.RegisterAttached("FontWeight", typeof(FontWeight), typeof(Object), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
if(e.NewValue!=null)
obj.SetValue(TextElement.FontWeightProperty, e.NewValue);
else
obj.ClearValue(TextElement.FontWeightProperty);
}
});
}
Обобщение для нескольких свойств
Обобщение этого может быть сделано несколькими способами. Один из них - создать обобщенный метод регистрации свойств, но при этом использовать несколько прикрепленных свойств:
public class OnlyIfSet
{
static DependencyProperty CreateMap(DependencyProperty prop)
{
return DependencyProperty.RegisterAttached(
prop.Name, prop.PropertyType, typeof(OnlyIfSet), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
if(e.NewValue!=null)
obj.SetValue(prop, e.NewValue);
else
obj.ClearValue(prop);
}
});
}
public static FontWeight GetFontWeight(DependencyObject obj) { return (FontWeight)obj.GetValue(FontWeightProperty); }
public static void SetFontWeight(DependencyObject obj, FontWeight value) { obj.SetValue(FontWeightProperty, value); }
public static readonly DependencyProperty FontWeightProperty =
CreateMap(TextElement.FontWeightProperty);
public static double GetFontSize(DependencyObject obj) { return (double)obj.GetValue(FontSizeProperty); }
public static void SetFontSize(DependencyObject obj, double value) { obj.SetValue(FontSizeProperty, value); }
public static readonly DependencyProperty FontSizeProperty =
CreateMap(TextElement.FontSizeProperty);
...
}
Разрешение произвольных свойств
Другой подход заключается в использовании двух прикрепленных свойств:
<Setter Property="my:ConditionalSetter.Property" Value="FontWeight" />
<Setter Property="my:ConditionalSetter.Value" Value="{Binding XPath=@font-weight}"/>
с кодом
public class ConditionalSetter : DependencyObject
{
public string GetProperty( ... // Attached property
public void SetProperty( ...
public static readonly DependencyProperty PropertyProperty = ...
{
PropertyChangedCallback = Update,
});
public object GetValue( ... // Attached property
public void SetValue( ...
public static readonly DependencyProperty ValueProperty = ...
{
PropertyChangedCallback = Update,
});
void Update(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var property = GetProperty(obj);
var value = GetValue(obj);
if(property==null) return;
var prop = DependencyPropertyDescriptor.FromName(property, obj.GetType(), typeof(object)).DependencyProperty;
if(prop==null) return;
if(value!=null)
obj.SetValue(prop, value);
else
obj.ClearValue(prop);
}
}