Привязать элемент к двум источникам - PullRequest
37 голосов
/ 04 ноября 2008

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

Мне было интересно, есть ли способ связать этот текстовый блок с обоими текстовыми полями и использовать собственный конвертер для вычисления среднего значения? В настоящее время я отслеживаю события изменения текста в обоих текстовых полях и рассчитываю среднее значение таким образом, но я считаю, что привязка данных будет более эффективной и простой.

Ответы [ 4 ]

56 голосов
/ 04 ноября 2008

Вы ищете MultiBinding.

Ваш XAML будет выглядеть примерно так:

<TextBlock>
  <TextBlock.Text>
    <MultiBinding Converter="{StaticResource myConverter}">
      <Binding Path="myFirst.Value" />
      <Binding Path="mySecond.Value" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>

При разумных заменах на myConverter, myFirst.Value и mySecond.Value.

35 голосов
/ 04 ноября 2008

Создать конвертер, который реализует IMultiValueConverter. Это может выглядеть примерно так:

class AverageConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int total = 0;
        int number = 0;
        foreach (object o in values)
        {
            int i;
            bool parsed = int.TryParse(o.ToString(), out i);
            if (parsed)
            {
                total += i;
                number++;
            }
        }
        if (number == 0) return 0;
        return (total/number).ToString();
    }

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

    #endregion
}

Многозначный преобразователь получает массив объектов, по одному для каждой привязки. Вы можете обработать их так, как вам нужно, в зависимости от того, хотите ли вы использовать double или int или что-то еще.

Если два текстовых поля привязаны к данным, вы можете использовать одинаковые привязки в мультисвязке для вашего текстового блока (не забывая уведомлять об изменении свойства, чтобы обновить среднее значение), или вы можете получить текстовое значение, ссылаясь на текстовые поля по ElementName.

<TextBox Text="{Binding Value1}" x:Name="TextBox1" />
<TextBox Text="{Binding Value2}" x:Name="TextBox2" />

<TextBlock>
   <TextBlock.Text>
      <MultiBinding Converter="{StaticResource AverageConverter}">
         <Binding ElementName="TextBox1" Path="Text" />
         <Binding ElementName="TextBox2" Path="Text" />
         <!--  OR  -->
         <!-- <Binding Path="Value1" />  -->
         <!-- <Binding Path="Value2" />  -->

      </MultiBinding>
   </TextBlock.Text>
</TextBlock>
2 голосов
/ 04 ноября 2008

Или, вы можете создать свойство в коде и связать TextBlock с этим ... Я делаю это все время, и это немного проще, чем сделать конвертер, затем сделать этот код там.

Пример: (в вашем коде за xaml):

public double AvgValue
{
    get { return (valueA + valueB) / 2.0; }
}

А потом, в вашем XAML:

<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=AvgValue}" />

Это НАМНОГО проще, чем пользовательский конвертер.

0 голосов
/ 05 декабря 2012

Просто добавьте пошаговую процедуру к ответу Тимоти:

  1. Установите свойство View.TextBlock.Text для привязки к свойству ViewModel.AvgValue.
  2. Перехватите событие TextChanged элемента управления TextBox, затем установите AvgValue в обработчике этого события TextChanged.
  3. Как часть этого обработчика на шаге 2, убедитесь, что вы вызвали изменение свойства для обновления TextBlock.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...