IValueConverter со связанными свойствами зависимости - PullRequest
9 голосов
/ 02 апреля 2012

Мне нужно определить StringFormat некоторого связанного TextBlocks во время выполнения на основе системы единиц, идентифицированной в объекте, который должен быть связан.

У меня есть конвертер со свойством зависимости, который я хотел быпривязать к.Значение привязки используется при определении процесса преобразования.

public class UnitConverter : DependencyObject, IValueConverter
{
    public static readonly DependencyProperty IsMetricProperty =
        DependencyProperty.Register("IsMetric", typeof(bool), typeof(UnitConverter), new PropertyMetadata(true, ValueChanged));

    private static void ValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        ((UnitConverter)source).IsMetric = (bool)e.NewValue;
    }

    public bool IsMetric
    {
        get { return (bool)this.GetValue(IsMetricProperty); }
        set { this.SetValue(IsMetricProperty, value); }
    }

    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (IsMetric)
            return string.Format("{0:0.0}", value);
        else
            return string.Format("{0:0.000}", value);
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Я объявляю преобразователь

<my:UnitConverter x:Key="Units" IsMetric="{Binding Path=IsMetric}"/>

и связываю TextBlock

<TextBlock Text="{Binding Path=Breadth, Converter={StaticResource Units}}" Style="{StaticResource Values}"/>

Тем не менее,Я получаю следующую ошибку:

System.Windows.Data Ошибка: 2: Не удается найти управляющий FrameworkElement или FrameworkContentElement для целевого элемента.BindingExpression: Path = IsMetric;DataItem = NULL;целевым элементом является UnitConverter (HashCode = 62641008);Свойство target - IsMetric (тип Boolean)

Я предполагаю, что это инициализируется до того, как я установлю текст данных, и поэтому нет ничего, с чем можно связать свойство IsMetric.Как мне достичь желаемого результата?

1 Ответ

8 голосов
/ 02 апреля 2012

При условии, что Breadth и IsMetric являются свойствами одного и того же объекта данных, вы можете использовать MultiBinding в сочетании с преобразователем нескольких значений :

<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource UnitMultiValueConverter}">
            <Binding Path="Breadth" />
            <Binding Path="IsMetric" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

с таким преобразователем:

public class UnitMultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        double value = (double)values[0];
        bool isMetric = (bool)values[1];
        string format = isMetric ? "{0:0.0}" : "{0:0.000}";
        return string.Format(format, value);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Проблема вашего подхода заключается в том, что когда UnitConverter объявлен как ресурс, он не имеет DataContext и никогда не получит его позже.

И еще одна важная вещь: обратный вызов ValueChanged для UnitConverter.IsMetric - нонсенс.Он снова устанавливает то же свойство, которое было только что изменено.

...