web-dev-qa-db-ja.com

要素を2つのソースにバインドする

現在、任意の数を受け入れる2つのテキストボックスがあります。入力した2つの数値を取り、平均を計算するテキストブロックがあります。

このテキストブロックを両方のテキストボックスにバインドし、カスタムコンバーターを使用して平均を計算する方法があるかどうか疑問に思っていましたか?現在、両方のテキストボックスでテキスト変更イベントをキャッチし、その方法で平均を計算していますが、データバインディングの方が効率的で簡単であると想定しています。

38
Nick

MultiBinding を探しています。

XAMLは次のようになります。

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

myConvertermyFirst.Value、およびmySecond.Valueの合理的な置き換え。

56
Jacob Carpenter

IMul​​tiValueConverterを実装するコンバーターを作成します。次のようになります。

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
}

複数値コンバーターは、バインディングごとに1つずつ、オブジェクト配列を受け取ります。 doubleまたはintなどの目的に応じて、必要に応じてこれらを処理できます。

2つのテキストボックスがデータバインドされている場合は、テキストブロックのマルチバインディングで同じバインディングを使用して(平均が更新されるようにプロパティが変更されたときに通知することを忘れないでください)、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>
36
Donnelle

または、コードビハインドでプロパティを作成し、それにTextBlockをバインドすることもできます。私はいつもそれを行っています。コンバーターを作成し、そこで同じコードを実行するよりも少し簡単です。

例:(xamlの背後にあるコード内):

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

そして、XAMLで:

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

これは、カスタムコンバーターよりもはるかにシンプルです。

2
Timothy Khouri

ティモシーの答えに段階的な手順を追加するだけです:

  1. ViewModel.AvgValueプロパティにバインドするようにView.TextBlock.Textプロパティを設定します。
  2. TextBoxコントロールのTextChangedイベントをキャッチし、そのTextChangedイベントのハンドラーでAvgValueを設定します。
  3. 手順2のそのハンドラーの一部として、TextBlockが更新されるようにプロパティの変更を発生させます。
0
Michael Nguyen