wpf 将一个元素绑定到两个源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/260439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 19:45:36  来源:igfitidea点击:

Bind an element to two sources

wpfbinding

提问by Nick

I currently have two text boxes which accept any number. I have a text block that takes the two numbers entered and calculates the average.

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

I was wondering if there was a way I could bind this text block to both text boxes and utilize a custom converter to calculate the average? I currently am catching the text changed events on both text boxes and calculating the average that way, but I am under the assumption data binding would be more efficient and easier.

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

回答by Jacob Carpenter

You're looking for MultiBinding.

您正在寻找MultiBinding.

Your XAMLwill look something like this:

XAML会看起来像这样:

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

With reasonable replacements for myConverter, myFirst.Value, and mySecond.Value.

随着合理的替代品myConvertermyFirst.ValuemySecond.Value

回答by Donnelle

Create a converter that implements IMultiValueConverter. It might look something like this:

创建一个实现 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
}

A multivalue converter receives an object array, one for each of the bindings. You can process these however you need, depending on whether you're intending it for double or int or whatever.

多值转换器接收一个对象数组,每个绑定一个。您可以根据需要处理这些,具体取决于您打算将其用于 double 还是 int 或其他。

If the two textboxes are databound, you can use the same bindings in the multibinding for your textblock (remembering to notify when the property changes so that your average is updated), or you can get the text value by referring to the textboxes by ElementName.

如果两个文本框是数据绑定的,您可以在文本块的多重绑定中使用相同的绑定(记住在属性更改时通知以便更新您的平均值),或者您可以通过 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>

回答by Timothy Khouri

Or, you could make a property in code behind, and bind the TextBlock to that ... I do that all the time, and it's a little simpler than making a converter, then doing that same code there.

或者,您可以在后面的代码中创建一个属性,然后将 TextBlock 绑定到该属性……我一直这样做,这比创建转换器简单一点,然后在那里执行相同的代码。

Example: (in your code behind of the xaml):

示例:(在 xaml 后面的代码中):

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

And then, in your XAML:

然后,在您的 XAML 中:

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

That's a LOT simpler than a custom converter.

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

回答by Michael Nguyen

Just to add step-by-step procedure to Timothy's answer:

只是在 Timothy 的回答中添加分步程序:

  1. Setup the View.TextBlock.Text property to bind to the ViewModel.AvgValue property.
  2. Catch the TextChanged event of the TextBox control, then set the AvgValue in the handler of that TextChanged event.
  3. As part of that handler in step 2, make sure to raise a property change so that the TextBlock is updated.
  1. 设置 View.TextBlock.Text 属性以绑定到 ViewModel.AvgValue 属性。
  2. 捕获 TextBox 控件的 TextChanged 事件,然后在该 TextChanged 事件的处理程序中设置 AvgValue。
  3. 作为第 2 步中该处理程序的一部分,请确保引发属性更改,以便更新 TextBlock。