![](/img/trans.png)
[英]WPF datagrid binding issue: first row bound but doesn't update selected item in two-way fashion
[英]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.