c# datagrid範例 與轉換器的雙向數據綁定不會更新源




wpf resource (3)

我有一個用轉換器設置的數據綁定,將一個尷尬的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實現了IValueConverterConvert方法被調用並返回非空數據,但是從不調用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方法?


Answer #1

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

我認為這將迫使綁定係統認識到目標方面有所改變。


Answer #2

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

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

viewModel像代理一樣工作,持有對象的引用,管理它的屬性,當然還實現INotifyPropertyChanged。 在這種情況下,您不需要調用ConvertBack方法,因為操作是通過viewModel在適當的實例上執行的。

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


Answer #3

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

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




two-way-binding