与转换器的双向数据绑定不会更新源 [英] Two-way data binding with converter doesn't update source
问题描述
我已经用转换器设置了数据绑定,以将笨拙的XML源转换为便于显示和编辑的内部类树.一切都非常适合从XML源读取,但是我有一段时间的魔鬼试图将对内部类所做的更改传播回XML源.
I've got a data binding set up with a converter to transform an awkward XML source to a display- and editing- convenient tree of internal classes. Everything works great for reading from the XML source, but I'm having a devil of a time trying to get changes made to the internal classes to propagate back to the XML source.
以下是使用网站的XAML:
Here's the XAML for the use site:
<local:SampleConverter x:Key="SampleConverter" />
<Expander Header="Sample" >
<local:SampleControl
Sample="{Binding Path=XmlSource,
Converter={StaticResource SampleConverter},
Mode=TwoWay}" />
</Expander>
XmlSource是父数据绑定对象的CLR读写属性(不是DependencyProperty).这是从XSD生成的.NET类型.
XmlSource is a CLR read-write property (not DependencyProperty) of the parent data bound object. It is a .NET type generated from an XSD.
SampleConverter实现 IValueConverter
.会调用 Convert
方法并返回非空数据,但永远不会调用 ConvertBack
方法.
SampleConverter implements IValueConverter
. The Convert
method is called and returns non-null data, but the ConvertBack
method is never called.
SampleControl是一个UserControl,它封装了与Sample数据树的UI交互.XAML看起来像这样:
SampleControl is a UserControl that encapsulates UI interaction with the Sample data tree. It's XAML looks like this:
<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>
在下面的SampleControl代码中,Sample属性是DependencyProperty:
The Sample property is a DependencyProperty in the SampleControl code behind:
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
}
XmlSource转换为实现INotifyPropertyChanged的内部类,并在树上发送更改通知,如上面MyPropertyChanged中的断点所示.
The internal classes that the XmlSource is converted to implement INotifyPropertyChanged, and are sending change notifications up the tree, as indicated by a breakpoint in MyPropertyChanged above.
因此,如果数据报告已更改,那么WPF为什么不调用转换器的ConvertBack方法?
So if the data is reporting that it has changed, why isn't WPF calling my converter's ConvertBack method?
推荐答案
在SO上有几个类似问题的提示和几乎答案,我有一个有效的解决方案可以保留绑定.您可以手动强制绑定以在策略性放置的事件(例如LostFocus)中更新源:
With hints from several similar questions and almost answers here on SO, I have a working solution that preserves the binding. You can manually force the binding to update the source in a strategically placed event, such as LostFocus:
private void mycontrol_LostFocus(object sender, RoutedEventArgs e)
{
if (mycontrol.IsModified)
{
var binding = mycontrol.GetBindingExpression(MyControl.SampleProperty);
binding.UpdateSource();
}
}
这篇关于与转换器的双向数据绑定不会更新源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!