2008-11-04 10 views
36

Actualmente tengo dos cuadros de texto que aceptan cualquier número. Tengo un bloque de texto que toma los dos números ingresados ​​y calcula el promedio.Enlazar un elemento a dos fuentes

Me preguntaba si había una forma de vincular este bloque de texto a ambos cuadros de texto y utilizar un convertidor personalizado para calcular el promedio. Actualmente estoy captando los eventos de texto modificado en ambos cuadros de texto y calculando el promedio de esa manera, pero estoy bajo la suposición de que el enlace de datos sería más eficiente y más fácil.

Respuesta

55

Está buscando MultiBinding.

Su XAML se verá algo como esto:

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

Con reemplazos razonables para myConverter, myFirst.Value y mySecond.Value.

+4

En caso de que desee pasar un valor de constancia a uno de los enlaces de multi-binding, ¿cómo puedo hacerlo? ¡Por favor ayuda! –

+0

@Jacob: Por error presiono el botón de votar y ahora me permite revertirlo y dice: "No puedo hasta la próxima edición" :-( –

33

Cree un convertidor que implemente IMultiValueConverter. Podría ser algo como esto:

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 
} 

Un convertidor de valores múltiples recibe una matriz de objetos, uno para cada uno de los enlaces. Puede procesarlos de la forma que necesite, dependiendo de si tiene la intención de duplicarlo o int o lo que sea.

Si las dos cajas de texto están unidas por datos, puede usar los mismos enlaces en la multibinding para su bloque de texto (recordando notificar cuando la propiedad cambia para que se actualice su promedio), o puede obtener el valor del texto refiriéndose al cuadros de texto por 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

O bien, puede hacer que una propiedad de código detrás, y obligar a la TextBlock a eso ... yo que todo el tiempo, y es un poco más simple de hacer un convertidor, a continuación, hacer eso mismo código que hay .

Ejemplo: (en su código detrás de la xaml):

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

Y luego, en su XAML:

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

eso es mucho más simple que un convertidor personalizado.

+0

Lo siento por aquellos de ustedes que vieron esto sin el XAML ... lo olvidé para espaciarlo ...está allí ahora :) –

+0

También puede poner un x: Name en su control y usarlo en el enlace de texto en lugar de RelativeSource :) – Donnelle

+0

Umm, eso no funciona. La propiedad AvgValue (en su ejemplo) no existe en la clase UserControl, y al cambiar el UserControl x: type al TableRow (la clase que tengo ampliando la clase UserControl) no encontrará el antecesor. Entonces, ¿puedes extender este ejemplo a una solución más funcional? – Nick

0

sólo para añadir procedimiento paso a paso para la respuesta de Timoteo:

  1. Configuración de la propiedad View.TextBlock.Text se una a la propiedad ViewModel.AvgValue.
  2. Capture el evento TextChanged del control TextBox, luego configure AvgValue en el controlador de ese evento TextChanged.
  3. Como parte de ese controlador en el paso 2, asegúrese de realizar un cambio de propiedad para que TextBlock se actualice.
Cuestiones relacionadas