2010-05-27 9 views
8

Esto comenzó con un comportamiento extraño que pensé que estaba atado a mi aplicación de ToString(), y me hizo esta pregunta: Why won't WPF databindings show text when ToString() has a collaborating object?Comportamiento de enlace WPF diferente cuando la propiedad enlazada se declara como interfaz frente a tipo de clase?

Resulta que no tienen nada que ver con los colaboradores y es reproducible.

Cuando Ato Label.Content a una propiedad de la DataContext que se declara como un tipo de interfaz, ToString() se llama en el objeto de tiempo de ejecución y la etiqueta muestra el resultado.

Cuando vinculo TextBlock.Text a la misma propiedad, nunca se llama a ToString() y no se muestra nada. Pero, si cambio la propiedad declarada a una implementación concreta de la interfaz, funciona como se esperaba.

¿Es esto de alguna manera por diseño? Si es así, ¿alguna idea de por qué?

para reproducir:

  • Cree una nueva aplicación de WPF (.NET 3.5 SP1)
  • Añadir las siguientes clases:
public interface IFoo 
{ 
    string foo_part1 { get; set; } 
    string foo_part2 { get; set; } 
} 

public class Foo : IFoo 
{ 
    public string foo_part1 { get; set; } 

    public string foo_part2 { get; set; } 

    public override string ToString() 
    { 
     return foo_part1 + " - " + foo_part2; 
    } 
} 
public class Bar 
{ 
    public IFoo foo 
    { 
     get { return new Foo {foo_part1 = "first", foo_part2 = "second"}; } 
    } 
} 
  • Establecer el XAML de Window1 a:

    <Window x:Class="WpfApplication1.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="Window1" Height="300" Width="300"> 
        <StackPanel> 
         <Label Content="{Binding foo, Mode=Default}"/> 
         <TextBlock Text="{Binding foo, Mode=Default}"/> 
        </StackPanel> 
    </Window> 
    
  • en Window1.xaml.cs:

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
     DataContext = new Bar(); 
    } 
} 

Cuando se ejecuta esta aplicación, verá el texto solo una vez (en la parte superior, en la etiqueta). Si cambia el tipo de propiedad foo en Bar clase a Foo (en lugar de IFoo) y ejecuta la aplicación nuevamente, verá el texto en ambos controles.

Respuesta

3

Sí, tienes razón. Obviamente, la propiedad ContentControl.Content se implementa de forma diferente a la propiedad TextBlock.Text. Una diferencia obvia, por supuesto, es que el ContentControl generará realmente una instancia TextBlock para un objeto de contenido que no es un Visual y no tiene un DataTemplate. El TextBlock no. Hará el texto por sí mismo.En ambos casos, la cadena se determina por

  1. la IValueConverter (si está presente en la unión)
  2. la TypeConverter (si se declara)
  3. object.ToString()

Parece que este algoritmo se diferencia sólo en paso 3 entre TextBlock y ContentControl como lo has mostrado. Mientras que ContentControl realmente resuelve el objeto detrás de la interfaz, el TextBlock no lo hace. Interesante.

Supongo que esto es algo con lo que tienes que vivir. Usted tiene varias opciones ahora:

  • exponer una propiedad de cadena en su interfaz y se unen a los que
  • Exponer el objeto de datos como una clase concreta en cambio, como una interfaz
  • Utilice un ContentControl en lugar de un TextBlock
  • proporcionan una IValueConverter y utilizarlo en la unión
  • proporcionar una TypeConverter para su interfaz de
  • hacer otra cosa (es probable que haya mor e)
8

Sé que este hilo es viejo, pero encontré una solución para este problema. Utilice la propiedad StringFormat sobre la unión:

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <Label Content="{Binding foo, Mode=Default}"/> 
     <TextBlock Text="{Binding foo, Mode=Default, StringFormat={}{0}}"/> 
    </StackPanel> 
</Window> 
+0

Henrik, [otra persona ha hecho una pregunta muy similar] (http://stackoverflow.com/questions/16309863/binding-to-interface-typed-properties), y cuando los relacioné con este, dijeron que tu respuesta resolvió su problema. Esa pregunta es tuya para responder si quieres; No quiero tomar el crédito cuando todo lo que hice fue encontrar una pregunta similar :) – shambulator

Cuestiones relacionadas