与转换器的双向数据绑定不会更新源 [英] Two-way data binding with converter doesn't update source

查看:64
本文介绍了与转换器的双向数据绑定不会更新源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经用转换器设置了数据绑定,以将笨拙的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆