2011-06-15 72 views
5

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

樣品屬性在後面的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方法?

+0

屬性更改您的代碼示例僅表示該樣品的特性正在發生變化,而不是樣品本身。 – Ragepotato 2011-06-15 20:52:30

+0

@Ragepotato:你是說數據綁定只適用於新實例分配給Sample屬性,但如果Sample屬性引用的現有實例的屬性發生更改並通過INotifyPropertyChanged發信號通知它們,則不適用? – dthorpe 2011-06-15 21:20:41

+0

是的。該示例從未改變。它是同一個對象。它內的屬性已更改。 你可以測試這個。在加載完所有內容後,將一個按鈕放在控件上,Sample從虛擬機獲取它的初始分配。然後將Sample指定給新的SampleType。記住它必須是正確的類型,否則綁定引擎會忽略它。如果你設置好雙向綁定,你會看到你的轉換被調用。 – Ragepotato 2011-06-16 05:56:14

回答

2

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

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

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

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

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

此外,關於此評論:

你是說的數據,如果一個新的實例分配給 樣本屬性綁定唯一 作品,但如果現有實例 的 性質的簡稱Sample屬性更改爲 ,並通過 INotifyPropertyChanged發出信號更改?

INotifyPropertyChanged的示例實現通常在屬性本身發生更改時發生通知,而不是在子級或其他屬性更改時發生。但是,您可以隨時在任何屬性上觸發通知事件。例如,您可能擁有「全名」屬性,只要「名字」或「姓氏」發生更改就會通知該屬性。

如果以上內容沒有幫助,我會建議發佈一些更多的代碼 - 也許是您嘗試工作的簡化版本。

編輯:

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

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

我認爲這將迫使結合系統識別的東西改變了目標端。

+0

XmlSource CLR屬性已經實現了INotifyPropertyChanged。此外,轉換器的ConvertBack將需要首先調用,以獲得一個值來分配給XmlSource屬性,並且不會調用ConvertBack。 – dthorpe 2011-06-16 17:45:10

0

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

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

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

讓您擁有一個乾淨的看法,你不需要在xaml.cs任何代碼