Я сам пришел с рабочим ответом из комментариев stukselbax ...
Короче говоря: Некоторый размер WPF или другое свойство меры мультисвязывается со статическим DependencyProperty Factor и некоторым статическим значениям удваивается как параметры (размер в мм, запасной размер в пикселях) через IMultiValueConverter.Статический Коэффициент исходит от одиночного.В синглтоне есть дополнительное событие FactorChanged , на которое могут подписаться другие классы.
Создание класса для использования в качестве экземпляра синглтона:
public class PPMMSingleton : DependencyObject
{
public double? Factor
{
get { return (double?)GetValue(FactorProperty); }
set { SetValue(FactorProperty, value); }
}
// Using a DependencyProperty as the backing store for Factor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FactorProperty =
DependencyProperty.Register("Factor", typeof(double?), typeof(PPMMSingleton),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsMeasure |
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault |
FrameworkPropertyMetadataOptions.Inherits,
new PropertyChangedCallback(OnFactorChanged),
new CoerceValueCallback(CoerceFactor)));
private static object CoerceFactor(DependencyObject element, object value)
{
return value;
}
public static void OnFactorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
PPMMSingleton ppmm = (PPMMSingleton)sender;
ppmmEventArgs e =
new ppmmEventArgs(
(double?)args.OldValue,
(double?)args.NewValue);
ppmm.OnFactorChanged(e);
}
private void OnFactorChanged(ppmmEventArgs e)
{
if (FactorChanged != null)
FactorChanged(e);
}
public event ppmmEventHandler FactorChanged;
}
Создание делегата и EventArgs дляFactorChanged:
public delegate void ppmmEventHandler(ppmmEventArgs e);
public class ppmmEventArgs : EventArgs
{
public ppmmEventArgs(double? oldFactor, double? newFactor)
{
OldFactor = oldFactor;
NewFactor = newFactor;
}
public double? OldFactor { get; private set; }
public double? NewFactor { get; private set; }
}
Создайте статический класс для размещения этого синглтона:
public static class PPMM
{
public static double? Factor
{
get { return Singleton.Factor; }
set
{
Singleton.Factor = value;
}
}
private static PPMMSingleton _singleton = null;
public static PPMMSingleton Singleton
{
get
{
if (_singleton == null)
_singleton = new PPMMSingleton();
return _singleton;
}
}
public static event ppmmEventHandler FactorChanged
{
add { Singleton.FactorChanged += value; }
remove { Singleton.FactorChanged -= value; }
}
}
Создайте IMultiValueConverter, который принимает Коэффициент, размер в мм и необязательный размер в пикселях в качестве запасного:
public class FactorAndMillimeterToPixelConverter : IMultiValueConverter
{
#region IMultiValueConverter Member
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((values.Length < 2)
|| !(values[0] is double?))
return Binding.DoNothing;
double? factor = (double?)values[0];
switch(values.Length)
{
case 2:
if(!(values[1] is double))
return Binding.DoNothing;
// values[0]: Factor, values[1]: SizeMM
// if Factor is null, no fallback provided -> donothing
if (!factor.HasValue)
return Binding.DoNothing;
// else return calculated width
return factor.Value * (double)values[1];
case 3:
if (!(values[1] is double) || !(values[2] is double))
return Binding.DoNothing;
// values[0]: Factor, values[1]: SizeMM, values[2]: SizePixelsFallback
// if Factor is null, but fallback provided -> return fallback
if (!factor.HasValue)
return (double)values[2];
// else return calculated width
return factor.Value * (double)values[1];
default:
// value.Length > 3
return Binding.DoNothing;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
Поместите ресурс с конвертером в ваш XAML:
<mynamespace:FactorAndMillimeterToPixelConverter x:Key="fm2pconv" />
MultiBind для свойства зависимости статического фактора и размера в мм и размера отступа в пикселях (какstatic doubles) в XAML:
<Border>
<Border.Width>
<MultiBinding Converter="{StaticResource fm2pconv}">
<MultiBinding.Bindings>
<Binding Path="Factor" Source="{x:Static tc:PPMM.Singleton}" />
<Binding>
<Binding.Source>
<sys:Double>50</sys:Double>
</Binding.Source>
</Binding>
<Binding>
<Binding.Source>
<sys:Double>400</sys:Double>
</Binding.Source>
</Binding>
</MultiBinding.Bindings>
</MultiBinding>
</Border.Width>
<TextBlock
Text="Wenn Factor gesetzt ist, ist dieser Kasten 50mm breit. Ansonsten ist er 400px breit. Seine Width wird beeinflusst."
TextWrapping="WrapWithOverflow"
>
</TextBlock>
</Border>
Можно также привязать размер в мм к свойству зависимости (при условии, что установлен правильный DataContext):
<Border.Width>
<MultiBinding Converter="{StaticResource fm2pconv}">
<MultiBinding.Bindings>
<Binding Path="Factor" Source="{x:Static tc:PPMM.Singleton}" />
<Binding Path="WidthInMMInCodeBehind" />
<Binding Path="FallbackWidthInPixelsInCodeBehind" />
</MultiBinding.Bindings>
</MultiBinding>
</Border.Width>
Voilà!