¿Por qué se actualiza el enlace sin implementar INotifyPropertyChanged?


Creé un ViewModel y vinculé su propiedad a dos cuadros de texto en la interfaz de usuario. El valor del otro cuadro de texto cambia cuando cambio el valor de first y focus fuera del cuadro de texto pero no estoy implementando INotifyPropertyChanged. ¿Cómo funciona esto?

Siguiente es XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <StackPanel>
        <TextBox Text="{Binding Name}" />
        <TextBox Text="{Binding Name}" />
    </StackPanel>
</Window>

Y siguiente es mi ViewModel

class ViewModel
{
    public string Name { get; set; }
}
Author: svick, 2011-10-14

3 answers

Lo probé, tienes razón. Ahora lo busqué en la web, y encontré esto .

Lamento tardar tanto en responder, en realidad se encuentra con otro aspecto oculto de WPF, es decir, el motor de enlace de datos de WPF enlazará los datos a la instancia de PropertyDescriptorque envuelve la propiedad de origen si el objeto de origen es un objeto CLR plano y no implementa la interfaz INotifyPropertyChanged. Y el motor de enlace de datos intentará suscríbase al evento property changed a través de PropertyDescriptor.Método AddValueChanged (). Y cuando el elemento enlazado a datos de destino cambie los valores de propiedad, data binding engine llamará a PropertyDescriptor.Método setValue () para transferir el valor cambiado de nuevo a la propiedad de origen, y simultáneamente elevará el evento valueChanged para notificar a otros suscriptores (en este caso, los otros suscriptores serán los bloques de texto dentro del ListBox.

Y si está implementando INotifyPropertyChanged, usted es totalmente responsable de implementar la notificación de cambio en cada configurador de las propiedades que necesitan ser datos vinculados a la interfaz de usuario. De lo contrario, el cambio no se sincronizará como esperarías.

Espero que esto aclare un poco las cosas.

Así que básicamente puedes hacer esto, siempre y cuando sea un objeto CLR simple. Bastante limpio pero totalmente inesperado-y he hecho un poco de trabajo WPF los últimos años. Nunca dejas de aprender cosas nuevas, ¿verdad?

Como sugirió Hasan Khan, aquí está otro enlace a un artículo bastante interesante sobre este tema.

Nota esto solo funciona cuando se usa binding. Si actualiza los valores desde code, el cambio no se notificará. [...]

WPF utiliza la clase PropertyInfo mucho más ligera cuando se enlaza. Si implementa explícitamente INotifyPropertyChanged, todo lo que WPF necesita hacer es llamar al PropertyInfo.Método GetValue para obtener el último valor. Eso es bastante menos trabajo que obtener todos los descriptores. Los descriptores terminan costando en el orden de 4 veces la memoria de las clases property info. [...]

Implementar INotifyPropertyChanged puede ser un poco tedioso trabajo de desarrollo. Sin embargo, tendrá que sopesar ese trabajo contra la huella de tiempo de ejecución (memoria y CPU) de su aplicación WPF. Implementando INPC usted mismo ahorrará CPU y memoria en tiempo de ejecución.

 46
Author: UrbanEsc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-14 12:38:33

Puedo explicar por qué la propiedad se actualiza cuando cambia el foco: todos los Binding tienen un UpdateSourceTrigger propiedad que indica cuando se actualizará la propiedad de origen. El valor predeterminado para esto se define en cada DependencyProperty y para la propiedad TextBox.Text se establece en LostFocus, lo que significa que la propiedad se actualizará cuando el control pierda el foco.

Creo que la respuesta de UrbanEsc explica por qué el valor se actualiza en absoluto

 1
Author: Steve Greatrex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-14 12:03:18

Acabo de descubrir que esto también funciona en WinForms, un poco: /

public class Test
{
    public bool IsEnabled { get; set; }
}

var test = new Test();
var btn = new Button { Enabled = false, Text = "Button" };
var binding = new Binding("Enabled", test, "IsEnabled");
btn.DataBindings.Add(binding);
var frm = new Form();
frm.Controls.Add(btn);
test.IsEnabled = true;
Application.Run(frm);

Aunque extrañamente, esto no desactiva el botón:

btn.Enabled = false;

Esto hace:

test.IsEnabled = false;
 1
Author: Viet Norm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-24 01:45:14