你能在数据绑定的 WPF 样式中做“数学”吗
Posted
技术标签:
【中文标题】你能在数据绑定的 WPF 样式中做“数学”吗【英文标题】:Can you do "math" within WPF Styles that are data-bound 【发布时间】:2010-09-24 13:52:16 【问题描述】:我有一个按钮控件样式,我想更改数据绑定版本的填充,以针对需要 2 像素偏移的字形进行调整。我将使用 SimpleStyles.xaml 中的 SimpleButton 作为示例(...为简洁起见,显示了删除触发器代码的位置):
<Style x:Key="SimpleButton" TargetType="x:Type Button" BasedOn="x:Null">
<Setter Property="FocusVisualStyle" Value="DynamicResource SimpleButtonFocusVisual"/>
<Setter Property="Background" Value="DynamicResource NormalBrush"/>
<Setter Property="BorderBrush" Value="DynamicResource NormalBorderBrush"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type Button">
<!-- We use Grid as a root because it is easy to add more elements to customize the button -->
<Grid x:Name="Grid">
<Border x:Name="Border" Background="TemplateBinding Background" BorderBrush="TemplateBinding BorderBrush" BorderThickness="TemplateBinding BorderThickness" Padding="TemplateBinding Padding"/>
<!-- Content Presenter is where the text content etc is placed by the control. The bindings are useful so that the control can be parameterized without editing the template -->
<ContentPresenter HorizontalAlignment="TemplateBinding HorizontalContentAlignment" Margin="TemplateBinding Padding" VerticalAlignment="TemplateBinding VerticalContentAlignment" RecognizesAccessKey="True"/>
</Grid>
...
</Setter.Value>
</Setter>
</Style>
我想要做的是在 Padding="TemplateBinding Padding" 的地方添加一些额外的边距。像 Padding="TemplateBinding Padding + 2,0,0,0"。
这有 XAML 语法吗?如果没有,在代码中执行此操作时是否有最佳方法(装饰器?)?
【问题讨论】:
【参考方案1】:目前 XAML 不解析 Binding 语法等中的表达式。但是,您可以使用 IValueConverter 或 IMultiValueConverter 来帮助自己:
XAML:
<Setter.Value>
<ControlTemplate TargetType="x:Type Button">
<Grid x:Name="Grid">
<Grid.Resources>
<local:ThicknessAdditionConverter x:Key="AdditiveThickness" />
</Grid.Resources>
<Border x:Name="Border">
<Border.Padding>
<Binding Path="Padding" RelativeSource="RelativeSource TemplatedParent"
Converter="StaticResource AdditiveThickness">
<Binding.ConverterParameter>
<Thickness>2,0,0,0</Thickness>
</Binding.ConverterParameter>
</Binding>
</Border.Padding>
</Border>
...
</Setter.Value>
IValueConverter 后面代码:
public class ThicknessAdditionConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
if (value == null) return new Thickness(0, 0, 0, 0);
if (!(value is Thickness)) throw new ArgumentException("Value not a thickness", "value");
if (!(parameter is Thickness)) throw new ArgumentException("Parameter not a thickness", "parameter");
var thickness = new Thickness(0, 0, 0, 0);
var t1 = (Thickness)value;
var t2 = (Thickness)parameter;
thickness.Left = t1.Left + t2.Left;
thickness.Top = t1.Top + t2.Top;
thickness.Right = t1.Right + t2.Right;
thickness.Bottom = t1.Bottom + t2.Bottom;
return thickness;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
throw new NotImplementedException();
【讨论】:
【参考方案2】:Blendables.com 上有一个产品,名为 Eval Binding,Simple Binding 现在可以做到这一点。 (该产品不是免费的)在这里查看whitepaper
例如,对于下面的 XAML 代码,您需要一个转换器来执行操作。
<Ellipse Fill="Blue" Height="50"
Width="Binding RelativeSource=RelativeSource Self,
Path=Height, Converter=StaticResource MyConverter" />
但是使用 EvalBinding 你可以像下面那样做
<Ellipse Fill="Blue" Height="50"
Width="blendables:EvalBinding [Self.Height]/2" />
【讨论】:
【参考方案3】:不,不在此版本的 XAML 中 - 使用值转换器进行数学运算。
【讨论】:
您能否提供一个使用值转换器进行此数学运算的示例 - 这对我来说更像是滥用。【参考方案4】:查看this library 中的ExpressionConverter
。
【讨论】:
【参考方案5】:您可以利用变换进行一些简单的数学运算。
查看 Charles Petzold 很久以前提出的这个技巧: http://www.charlespetzold.com/blog/2006/04/060223.html
不幸的是,它似乎对您的特定场景没有帮助...因为您只想更改 Padding 的厚度类型的 Left 属性...而且这不是您可以单独绑定的依赖属性。
但是,我觉得有必要添加这个答案,因为它可以帮助其他人通过 Google 或其他搜索引擎找到他们的方式。
【讨论】:
【参考方案6】:查看 MathConverter:http://rachel53461.wordpress.com/2011/08/20/the-math-converter/
您可以在此处发送一个表达式作为转换器参数,其中@VALUE 是您要绑定的值:
ConverterParameter=((@VALUE-15)*.2)
【讨论】:
以上是关于你能在数据绑定的 WPF 样式中做“数学”吗的主要内容,如果未能解决你的问题,请参考以下文章