【问题标题】:Can you do "math" within WPF Styles that are data-bound你能在数据绑定的 WPF 样式中做“数学”吗
【发布时间】: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 语法吗?如果没有,在代码中执行此操作时是否有最佳方法(装饰器?)?

【问题讨论】:

    标签: wpf data-binding templates styles


    【解决方案1】:

    目前 XAML 不解析 Binding 语法等中的表达式。但是,您可以使用 IValueConverterIMultiValueConverter 来帮助自己:

    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 BindingSimple 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)
            

            【讨论】:

              猜你喜欢
              • 2019-12-05
              • 2010-11-20
              • 2011-02-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-03-06
              相关资源
              最近更新 更多