español data c# wpf xaml data-binding two-way-binding

c# - data - El enlace de datos bidireccional con el convertidor no actualiza la fuente



binding wpf español (3)

XmlSource es una propiedad de lectura y escritura CLR (no DependencyProperty) del objeto primario vinculado a datos. Es un tipo .NET generado desde un XSD.

Creo que este es tu problema Una propiedad CLR básica no notificará y, por lo tanto, no podrá participar en el enlace de datos bidireccional. ¿Supongo que recibirás un enlace por única vez? ¿Tiene algún error de enlace de datos en su ventana de salida?

Puede intentar crear un contenedor que contenga la clase de la propiedad XmlSource, hacer que esa clase implemente INotifyPropertyChanged y exponer XmlSource como una propiedad de notificación (no es necesario que sea una propiedad de dependencia).

Además, con respecto a este comentario:

¿Está diciendo que el enlace de datos solo funciona si se asigna una nueva instancia a la propiedad Muestra, pero no si las propiedades de la instancia existente referida por la propiedad Muestra se modifican y señalan sus cambios a través de INotifyPropertyChanged?

Las implementaciones de muestra de INotifyPropertyChanged generalmente tienen la notificación ocurriendo cuando la propiedad misma cambia, no cuando cambian los elementos secundarios u otras propiedades. Sin embargo, puede activar el evento de notificación en cualquier propiedad en cualquier momento. Por ejemplo, puede tener una propiedad de "Nombre completo" que notifica cada vez que cambian "Nombre" o "Apellido".

Si lo anterior no es útil, le sugiero que publique un poco más de su código, tal vez una reproducción simplificada de lo que está intentando hacer funcionar.

Editar:

Creo que malentendí tu pregunta. Creo que el problema es a lo que aludiste en tus comentarios, es un tipo de referencia. Puede valer la pena intentar esto en su OnSampleChanged:

private static void OnSampleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var oldValue = Sample; Sample = new SampleType(); Sample = oldValue; }

Creo que esto obligará al sistema vinculante a reconocer que algo cambió en el lado del objetivo.

Tengo un enlace de datos configurado con un convertidor para transformar una fuente XML incómoda en un árbol de clases internas de visualización y edición. Todo funciona muy bien para leer desde el origen XML, pero me está costando muchísimo intentar que los cambios realizados en las clases internas se propaguen nuevamente a la fuente XML.

Aquí está el XAML para el sitio de uso:

<local:SampleConverter x:Key="SampleConverter" /> <Expander Header="Sample" > <local:SampleControl Sample="{Binding Path=XmlSource, Converter={StaticResource SampleConverter}, Mode=TwoWay}" /> </Expander>

XmlSource es una propiedad de lectura y escritura CLR (no DependencyProperty) del objeto primario vinculado a datos. Es un tipo .NET generado desde un XSD.

SampleConverter implementa IValueConverter . Se llama al método Convert y devuelve datos no nulos, pero nunca se llama al método ConvertBack .

SampleControl es un UserControl que encapsula la interacción de UI con el árbol de datos de muestra. Es XAML se ve así:

<UserControl x:Class="SampleControl"> [... other stuff ...] <UserControl.Content> <Binding Path="Sample" RelativeSource="{RelativeSource Mode=Self}" Mode="TwoWay" TargetNullValue="{StaticResource EmptySampleText}" /> </UserControl.Content> <UserControl.ContentTemplateSelector> <local:BoxedItemTemplateSelector /> </UserControl.ContentTemplateSelector> </UserControl>

La propiedad Sample es DependencyProperty en el código SampleControl detrás de:

public static readonly DependencyProperty SampleProperty = DependencyProperty.Register("Sample", typeof(SampleType), typeof(SampleControl), new PropertyMetadata(new PropertyChangedCallback(OnSampleChanged))); public SampleType Sample { get { return (SampleType)GetValue(SampleProperty); } set { SetValue(SampleProperty, value); } } private static void OnSampleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (e.NewValue != null) { ((INotifyPropertyChanged)e.NewValue).PropertyChanged += ((SampleControl)d).MyPropertyChanged; } else if (e.OldValue != null) { ((INotifyPropertyChanged)e.OldValue).PropertyChanged -= ((SampleControl)d).MyPropertyChanged; } } private void MyPropertyChanged(object sender, PropertyChangedEventArgs e) { ; // breakpoint here shows change notices are happening }

Las clases internas en las que XmlSource se convierte para implementar INotifyPropertyChanged y están enviando notificaciones de cambio al árbol, como lo indica un punto de interrupción en MyPropertyChanged anterior.

Entonces, si los datos informan que ha cambiado, ¿por qué WPF no está llamando al método ConvertBack de mi convertidor?


Con sugerencias de varias preguntas similares y casi respuestas aquí en SO, tengo una solución de trabajo que preserva el enlace. Puede forzar manualmente el enlace para actualizar la fuente en un evento estratégicamente ubicado, como LostFocus:

private void mycontrol_LostFocus(object sender, RoutedEventArgs e) { if (mycontrol.IsModified) { var binding = mycontrol.GetBindingExpression(MyControl.SampleProperty); binding.UpdateSource(); } }


Tenía un problema similar. La solución fue la siguiente:

En lugar del enlace bidireccional, utilicé una forma y un convertidor. El convertidor convierte (encapsula) el objeto (en su caso, el objeto principal de la propiedad xmlsource) en un viewModel, y el control se une a él.

ViewModel funciona como un proxy, contiene una referencia al objeto, administra sus propiedades y, por supuesto, implementa INotifyPropertyChanged. En este caso, no necesita llamar al método ConvertBack, ya que las operaciones se realizan en la instancia adecuada a través de viewModel.

Para que tenga una vista limpia, no necesita ningún código en xaml.cs