나는 사용자 정의 setter 클래스를 작성하여 문제를 해결할 수있었습니다. 그것이 작동되도록하기 위해서, 나는 정상 세터의 속성이 아닌 다른 속성을 사용할 수 있습니다
PropertyName
는
Binding
이 재산
Value
에 할당 할 바인딩 보유하고있는 프로퍼티의 이름을 보관 유지 속성에 할당 할 고정 값을 보유합니다.
및 Value
중 하나만 설정해야합니다.
속성 이름과 바인딩/값은 세터의 실제 값인 단일 개체로 결합됩니다. setter의 실제 대상은 동적으로 생성 된 DependencyProperty입니다 (실제 속성마다 하나씩).
솔루션의 핵심은 이러한 속성의 PropertyChangedCallback에서 첫 번째 인수가 실제 대상 개체라는 것입니다. 이 객체에서 리플렉션을 통해 속성을 가져오고 바인딩/값을 할당합니다.
전체 코드 :
public class UnsafeSetter : Setter
{
private class ValueContainer
{
public string Property { get; set; }
public object Value { get; set; }
}
private static readonly Dictionary<string, DependencyProperty> _properties = new Dictionary<string, DependencyProperty>();
private DependencyProperty GetOrAddProperty(string name)
{
DependencyProperty res;
if (!_properties.TryGetValue(name, out res))
{
res = DependencyProperty.RegisterAttached(
"Intermediate_" + name,
typeof(ValueContainer),
typeof(UnsafeSetter),
new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPropertyChanged)));
_properties.Add(name, res);
}
return res;
}
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var args = (ValueContainer)e.NewValue;
var prop = GetDependencyProperty(d.GetType(), args.Property);
if (prop == null)
{
throw new ArgumentException(string.Format("Dependency property {0} not found on type {1}", args.Property, d.GetType().Name));
}
else
{
var binding = args.Value as BindingBase;
if (binding != null)
{
BindingOperations.SetBinding(d, prop, binding);
}
else
{
d.SetValue(prop, args.Value);
}
}
}
private static DependencyProperty GetDependencyProperty(Type type, string name)
{
if (type == null)
return null;
FieldInfo fieldInfo = type.GetField(name + "Property", BindingFlags.Public | BindingFlags.Static);
if (fieldInfo == null)
return GetDependencyProperty(type.BaseType, name);
return (DependencyProperty)fieldInfo.GetValue(null);
}
private string _unsafeProperty;
public string PropertyName
{
get { return _unsafeProperty; }
set
{
_unsafeProperty = value;
UpdateBaseValue();
base.Property = GetOrAddProperty(value);
}
}
private object _unsafeValue;
public BindingBase Binding
{
get { return _unsafeValue as BindingBase; }
set
{
_unsafeValue = value;
UpdateBaseValue();
}
}
public new object Value
{
get { return _unsafeValue; }
set
{
_unsafeValue = value;
UpdateBaseValue();
}
}
private void UpdateBaseValue()
{
base.Value = new ValueContainer
{
Property = PropertyName,
Value = Value
};
}
}
사용법 :
<Style x:Key="ButtonStyle">
<Style.Setters>
<utilities:UnsafeSetter PropertyName="Label" Value="This is a static value" />
<utilities:UnsafeSetter PropertyName="LargeIcon" Binding="{Binding IconKey, Converter={StaticResource ResourceKeyConverter}}" />
<utilities:UnsafeSetter PropertyName="SmallIcon" Binding="{Binding RelativeSource={RelativeSource Self}, Path=LargeIcon}" />
</Style.Setters>
</Style>
<syncfusion:RibbonButton Style="{StaticResource ButtonStyle}" />
<syncfusion:DropDownButton Style="{StaticResource ButtonStyle}" />
<syncfusion:SplitButton Style="{StaticResource ButtonStyle}" />
나는이 나와 같은 문제에 직면하고 다른 사람을 도울 수 있기를 바랍니다. 의견이나 개선 사항을 자유롭게 공유하십시오!
당신이 할 수있는 일은 그 개별적인 부분들을 떼어내어 staticresource로 만드는 것입니다. 당신은 각각에 적용 할 수 있습니다. 그래서 그들은 둘 다 공유합니다. 예를 들어 Label이 String이기 때문에' 나는 리본 메뉴의 라벨이고'과 같이 할 수 있고'Label = " {StaticResource MySharedRibbonButtonLabel} ","각 속성에 대한 등등. –