Подтвердить что ты не робот

Свяжите элемент с двумя источниками

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

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

4b9b3361

Ответ 1

Вы ищете 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.

Ответ 2

Создайте конвертер, который реализует 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>

Ответ 3

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

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

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

И затем, в вашем XAML:

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

Это намного проще, чем собственный конвертер.

Ответ 4

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

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