簡體   English   中英

與轉換器的雙向數據綁定不會更新源

[英]Two-way data binding with converter doesn't update source

我有一個數據綁定設置與轉換器,以將一個笨拙的XML源轉換為顯示和編輯方便的內部類樹。 一切都非常適合從XML源讀取,但我有一段時間試圖對內部類進行更改以傳播回XML源。

這是使用網站的XAML:

        <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類型。

SampleConverter實現了IValueConverter 調用Convert方法並返回非null數據,但從不調用ConvertBack方法。

SampleControl是一個UserControl,它封裝了與Sample數據樹的UI交互。 這是XAML看起來像這樣:

<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>

Sample屬性是SampleControl代碼中的DependencyProperty:

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中的斷點所示。

因此,如果數據報告它已經改變,為什么WPF不調用我的轉換器的ConvertBack方法?

通過幾個類似問題的提示和SO上的幾乎答案,我有一個保留綁定的工作解決方案。 您可以手動強制綁定在策略性放置的事件中更新源,例如LostFocus:

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

有類似的問題。 解決方案如下:

而不是雙向綁定我用一種方式,和轉換器。 轉換器將對象(在您的情況下,xmlsource屬性的父對象)轉換(封裝)到viewModel,並且控件綁定到它。

viewModel的工作方式類似於代理,包含對象的引用,管理它的屬性,當然還實現了INotifyPropertyChanged。 在這種情況下,您不需要調用ConvertBack方法,因為操作是通過viewModel在適當的實例上執行的。

所以你有一個干凈的視圖,你不需要xaml.cs中的任何代碼

XmlSource是父數據綁定對象的CLR讀寫屬性(不是DependencyProperty)。 它是從XSD生成的.NET類型。

我相信這是你的問題。 基本CLR屬性不會通知,因此無法參與雙向數據綁定。 我的猜測是你的一次性綁定? 輸出窗口中是否有任何數據綁定錯誤?

您可以嘗試創建包含XmlSource屬性的類的包裝,對該類執行INotifyPropertyChanged,並公開XmlSource作為通知特性(它並不需要是一個依賴屬性)。

另外,關於這個評論:

您是說數據綁定僅在將新實例分配給Sample屬性時才有效,但是如果Sample屬性引用的現有實例的屬性發生更改並且通過INotifyPropertyChanged發出更改信號,則不會這樣做嗎?

INotifyPropertyChanged的示例實現通常會在屬性本身更改時發生通知,而不是在子項或其他屬性發生更改時。 但是,您可以隨時在任何屬性上觸發通知事件。 例如,您可能具有“全名”屬性,該屬性會在“名字”或“姓氏”發生變化時通知。

如果以上內容沒有幫助,我建議您發布一些代碼 - 可能是您正在努力工作的簡化版本。

編輯:

我想我誤解了你的問題。 我認為問題是你在評論中提到的 - 它是一種參考類型。 可能值得在你的OnSampleChanged中嘗試這個:

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

我認為這將迫使綁定系統識別出目標端發生了某些變化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM