Как вы изменяете связанное значение, меняете его, умножаете, вычитаете или добавляете к нему? - PullRequest
15 голосов
/ 11 февраля 2011

Во-первых; вопрос риторический, у меня есть ответ! Я получил такую ​​помощь от осмотра здесь, что хотел вернуть этот аккуратный трюк.

Представьте, что у вас есть значение, к которому вы хотите привязаться, но оно как-то или несколько неверно.

  • У меня была ситуация, когда я хотел привязать к значению, но когда значение было 1, мне нужно было 0, и наоборот.
  • Было время, когда я хотел привязать ширину элемента к ширине родительского элемента - 68 пикселей.

Ответы [ 2 ]

13 голосов
/ 11 февраля 2011

Введите FirstDegreeFunctionConverter :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;

namespace GenericWPF
{
    /// <summary>
    /// Will return a*value + b
    /// </summary>
    public class FirstDegreeFunctionConverter : IValueConverter
    {
        public double A { get; set; }
    public double B { get; set; }

    #region IValueConverter Members

    public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
    {
        double a = GetDoubleValue( parameter, A );

        double x = GetDoubleValue( value, 0.0 );

        return ( a * x ) + B;
    }

    public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
    {
        double a = GetDoubleValue( parameter, A );

        double y = GetDoubleValue( value, 0.0 );

        return ( y - B ) / a;
    }

    #endregion


    private double GetDoubleValue( object parameter, double defaultValue )
    {
        double a;
        if( parameter != null )
            try
            {
                a = System.Convert.ToDouble( parameter );
            }
            catch
            {
                a = defaultValue;
            }
        else
            a = defaultValue;
        return a;
    }
}

Как его использовать?

Вы создаете ресурс для каждого использования в разделе ресурсов:

<GenericWPF:FirstDegreeFunctionConverter x:Key="ReverseOne"
                            A="-1"
                            B="1" />

<Border Opacity="{Binding Path=Opacity
    , ElementName=daOtherField
    , Converter={StaticResource ReverseOne}}" />

<GenericWPF:FirstDegreeFunctionConverter x:Key="ListboxItemWidthToErrorWidth"
     A="1"
     B="-68" />

<TextBox MaxWidth="{Binding Path=ActualWidth
   , Converter={StaticResource ListboxItemWidthToErrorWidth}
   , RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />

Имя происходит от функции y = a * x + b (На норвежском языке называется "функцией первой степени")), и, конечно, можно было бы обновить его до функции второй степени y = a * x ^ 2 + bx + c, но я пока не нашел в этом применения.

У меня былСитуация, когда я хотел сделать столбцы на основе ширины.Каждый раз, когда я получал на 200 пикселей больше ширины, я хотел, чтобы контейнер показывал мне другой столбец.В то время я жестко закодировал конвертер, но вместо этого я должен был сделать конвертер ay = (a / x) + b.

Теперь, как я должен был назвать этот конвертер, чтобы все поняли, что это такое?Поскольку я норвежец, я использовал выражение, которое мы выучили в школе, прямо переведенное.Пожалуйста, если у вас есть предложение или мнение, дайте мне знать.Любые уточнения или улучшения, о которых вы подумали, также будут оценены ...


Может быть, " LinearTransformConverter " будет лучше сообщать, что конвертер делает для вас, я подумаю об этом,Есть еще предложения?Tor

6 голосов
/ 02 мая 2011

Что еще лучше, это PolynomialConverter, вот односторонняя версия:

public class PolynomialConverter : IValueConverter
{
    public DoubleCollection Coefficients { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double x = (double)value;
        double output = 0;
        for (int i = Coefficients.Count - 1; i >= 0 ; i--)
            output += Coefficients[i] * Math.Pow(x, (Coefficients.Count - 1) - i);

        return output;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //This one is a bit tricky, if anyone feels like implementing this...
        throw new NotSupportedException();
    }
}

Примеры:

<!-- x^2 -->
<vc:PolynomialConverter Coefficients="1,0,0"/>
<!-- x + 5 -->
<vc:PolynomialConverter Coefficients="1,5"/>
<!-- 2x + 4 -->
<vc:PolynomialConverter Coefficients="2,4"/>

В качестве альтернативы можно использовать вместо ConverterParameterне устанавливать коэффициенты в самом конвертере.

DoubleCollection coefficients = DoubleCollection.Parse((string)parameter);
//...
...