我有一个GUI,其元素应以毫米为单位显示特定大小
为此,我有一个(全局)静态类PPMM
(=每毫米像素数),double? Factor
和event FactorChanged
都是静态的。 Factor
的设置者调用FactorChanged
事件处理程序
GUI中的元素是UserControls和FactorChanged
事件的钩子(在构造函数中)以更新其像素大小或ScaleTransforms。
在布局GUI时,我不想为每个要以毫米为单位的对象创建UserControl。
相反,我想以
<elem Margin="0, {?:getPixelsFromMillimeters(
desiredSize:{x:Const 20mm},
fallback:{x:Const 80px})}" />
mm size 和后备像素大小应该是可绑定的。
我考虑过绑定到Factor
并在转换器的IValueConverter
中使用所需 mm size 的parameter
。但是我无法绑定到变量 mm size 值。
我可以绑定到 mm size 并使用转换器,但随后更改Factor
将不会更新该度量。
我也没有设法在静态类中创建DependencyProperty(GetValue
并且SetValue
在那里不可用),但那将是一个不同的SO问题......
有什么方法可以实现我的目标?
我还有没有回复的详细信息?如果是,请发表评论。
答案 0 :(得分:0)
我从stukselbax的评论中得出了一个有效的答案......
简而言之:某些WPF大小或其他度量属性多重绑定到静态DependencyProperty 因子和一些静态双精度作为参数(大小以mm为单位,后退大小以像素为单位)通过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;
}
为FactorChanged创建委托和EventArgs:
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到XAML中的静态Factor依赖项属性和mm的大小以及像素的后备大小(两者都是静态双精度):
<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>
还可以将mm的大小绑定到依赖项属性(假设设置了正确的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>
瞧!