2009-05-10 14 views
14

Decir que tengo un control de usuario muy simple que - para todos los intentos y propósitos - no es más que Cuadro de texto:Configuración de las propiedades personalizadas de control de usuario a través de DataBinding

public partial class FooBox : UserControl 
{ 
    public static readonly DependencyProperty FooTextProperty = 
     DependencyProperty.Register("FooText", typeof(string), typeof(FooBox)); 

    public FooBox() 
    { 
     InitializeComponent(); 
    } 

    public string FooText 
    { 
     get { return textBlock.Text; } 
     set { textBlock.Text = value; } 
    } 
} 

<UserControl x:Class="Namespace.FooBox" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Height="300" Width="300"> 
    <Grid> 
     <TextBlock x:Name="textBlock" /> 
    </Grid> 
</UserControl> 

En el formulario se declara como:

<local:FooBox FooText="{Binding Name}" /> 

El DataContext del formulario se establece en un objeto que tiene una propiedad Name. Pero esto no está funcionando para mí. ¿Qué me estoy perdiendo?

Respuesta

5

Resulta que el problema real es que esperaba que el marco WPF estableciera mi propiedad pública, por lo que mi código respondería a los cambios y los renderizaría según el nuevo valor. No tan. Lo que hace WPF es llamar a SetValue() directamente y eludir por completo la propiedad pública. Lo que tenía que hacer era recibir notificaciones de cambio de propiedad usando DependencyPropertyDescriptor.AddValueChanged y responder a eso. Parece algo así como (dentro del ctor):

var dpd = DependencyPropertyDescriptor 
    .FromProperty(MyDependencyProperty, typeof(MyClass)); 
dpd.AddValueChanged(this, (sender, args) => 
{ 
    // Do my updating. 
}); 
+4

También tenga en cuenta que el método de registro para propiedades de dependencia tiene sobrecargas que pueden aceptar controladores de eventos que se activan cada vez que la propiedad está cambiando o ha cambiado. Ese podría ser un lugar para poner la lógica que tienes allí. –

19

Las partes "get" y "set" de una declaración de propiedad en DependencyProperty en realidad no son llamadas por el sistema de enlace de datos de WPF; básicamente están ahí para satisfacer solo al compilador.

En su lugar, cambiar su declaración de propiedad a tener este aspecto:

public string FooText 
{ 
    get { return (string)GetValue(FooTextProperty); } 
    set { SetValue(FooTextProperty, value); } 
} 

... y su XAML a:

<UserControl ... 
    x:Name="me"> 
    <Grid> 
     <TextBlock Text="{Binding FooText,ElementName=me}" /> 
    </Grid> 
</UserControl> 

Ahora sus TextBox.Text simplemente se une directamente a la "footext" propiedad, por lo que a su vez puede vincular la propiedad FooText a "Nombre" tal como lo hace actualmente.

Otra forma es vincular TextBlock.Text a un enlace RelativeSource que encuentra la propiedad FooText en el primer antecesor de tipo "FooBox", pero he encontrado que esto es más complejo que simplemente darle al control una x interna: Nombre y uso del enlace del elemento.

+0

Te votaré porque me ayudaste a acercarte a lo que me estaba perdiendo. Pero mi caso de prueba aquí era demasiado simple para exponer el problema real. Ver mi respuesta – xanadont

Cuestiones relacionadas