Можете ли вы сделать "математику" в стилях WPF, которые связаны с данными - PullRequest
9 голосов
/ 29 ноября 2008

У меня есть стиль управления кнопками, и я хочу изменить отступ от любой версии с привязкой к данным, чтобы настроить глиф, для которого требуется смещение в 2 пикселя. Я буду использовать SimpleButton из SimpleStyles.xaml в качестве примера (... показывает, где код триггера был удален для краткости):

<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 для этого? Если нет, то есть ли лучший подход при выполнении этого в коде (декоратор?)?

Ответы [ 6 ]

9 голосов
/ 30 ноября 2008

В настоящее время 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();
    }
}
3 голосов
/ 29 ноября 2008

Существует продукт, доступный на Blendables.com , называемый Eval Binding и Simple Binding делает это сейчас. (Продукт не бесплатный) Ознакомьтесь с технической документацией здесь

Например, для приведенного ниже кода 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}" />
2 голосов
/ 30 ноября 2008

Проверьте ExpressionConverter в этой библиотеке .

2 голосов
/ 29 ноября 2008

Нет, не в этой версии XAML - используйте преобразователь значений, чтобы сделать свою математику.

1 голос
/ 25 марта 2013

Проверьте MathConverter: http://rachel53461.wordpress.com/2011/08/20/the-math-converter/

Там вы можете отправить выражение в качестве параметра-преобразователя, где @VALUE - значение, к которому вы привязываете:

ConverterParameter=((@VALUE-15)*.2)
1 голос
/ 04 августа 2011

Вы можете сделать простую математику, используя преимущества преобразований.

Посмотрите на этот трюк, который Чарльз Петцольд придумал давно: http://www.charlespetzold.com/blog/2006/04/060223.html

К сожалению, похоже, это не поможет вашему конкретному сценарию ... поскольку вы хотите изменить только свойство Left типа Thickness для отступа ... и это не свойство зависимости, которое вы можете привязать к одному.

Однако я чувствовал себя обязанным добавить этот ответ в случае, если он помогает другим, кто находит свой путь здесь через Google или другую поисковую систему.

...