【问题标题】:Bind an element to two sources将一个元素绑定到两个源
【发布时间】:2010-09-20 14:24:07
【问题描述】:

我目前有两个可以接受任何数字的文本框。我有一个文本块,它接受输入的两个数字并计算平均值。

我想知道是否有一种方法可以将此文本块绑定到两个文本框并使用自定义转换器来计算平均值?我目前正在捕获两个文本框上的文本更改事件并以这种方式计算平均值,但我假设数据绑定会更有效、更容易。

【问题讨论】:

    标签: wpf binding


    【解决方案1】:

    只是在蒂莫西的回答中添加分步程序:

    1. 设置 View.TextBlock.Text 属性以绑定到 ViewModel.AvgValue 属性。
    2. 捕捉 TextBox 控件的 TextChanged 事件,然后在该 TextChanged 事件的处理程序中设置 AvgValue。
    3. 作为第 2 步中该处理程序的一部分,请确保引发属性更改,以便更新 TextBlock。

    【讨论】:

      【解决方案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 或其他。

      如果两个文本框是数据绑定的,你可以在你的文本块的多重绑定中使用相同的绑定(记得在属性改变时通知,以便更新你的平均值),或者你可以通过引用文本框来获取文本值按元素名称。

      <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}" />
        

        这比自定义转换器简单得多。

        【讨论】:

        • 对于那些在没有 XAML 的情况下看到此内容的人感到抱歉...我忘了给它加空格...它现在就在那里 :)
        • 您也可以在您的控件上放置一个 x:Name 并在文本绑定中使用它而不是 RelativeSource :)
        • 嗯,这行不通。 UserControl 类中不存在 AvgValue 属性(在您的示例中),并且将 UserControl x:type 更改为 TableRow (我扩展了 UserControl 类的类)不会找到祖先。那么你能把这个例子扩展到一个更有效的解决方案吗?
        • 但是通过创建另一个属性来使用TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=AvgValue} 会消耗额外的内存,比如如果对象收集数量很大。
        【解决方案4】:

        您正在寻找MultiBinding

        您的XAML 将如下所示:

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

        myConvertermyFirst.ValuemySecond.Value 进行合理替换。

        【讨论】:

        • 如果我想将一个常量值传递给多重绑定的绑定之一,我该怎么做?请帮忙!
        • @Jacob :我不小心按下了投票按钮,现在它确实允许我恢复它并说 - “我不能直到下一次编辑”:-(
        猜你喜欢
        • 1970-01-01
        • 2012-10-13
        • 2013-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-24
        • 1970-01-01
        相关资源
        最近更新 更多