2011-02-02 64 views
31

OneWayToSource綁定似乎打破了.NET 4.0OneWayToSource綁定似乎打破了.NET 4.0

我有這個簡單的一塊XAML中

<StackPanel> 
    <TextBox Text="{Binding TextProperty, Mode=OneWayToSource}"/> 
    <Button/> 
</StackPanel> 

和我後面的代碼看起來像這樣

public MainWindow() 
{ 
    InitializeComponent(); 
    this.DataContext = this; 
} 
private string m_textProperty; 
public string TextProperty 
{ 
    get 
    { 
     return "Should not be used in OneWayToSource Binding"; 
    } 
    set 
    { 
     m_textProperty = value; 
    } 
} 

在.NET 3.5中這可以像你可能除外。放入TextBox一些文本,按Tab鍵使其失去焦點,而TextProperty更新與任何文本是在TextBox

進入在.NET 4.0,如果我鍵入TextBox一些文字,然後按選項卡使它失去焦點,TextBox恢復爲TextProperty(意思是「不應用於OneWayToSource綁定」)的值。這是否重新閱讀了.NET 4.0中的OneWayToSource Binding?我只是想TextBox將其價值推到TextProperty而不是相反。

更新
加入懸賞這個問題,因爲這已經成爲我的項目市長不便,我想知道,這種情況已經改變的原因。看起來,綁定已更新源後調用get。這是在.NET 4.0中綁定的OneWayToSource所需的行爲嗎?

如果是

  • 知道是怎麼在3.5的工作方式的問題?
  • 這種新行爲在哪些情況下更好?

或者是這樣,其實我們可以希望錯誤得到固定在未來的版本?

回答

9

卡爾Shifflett的博客和@ Simpzon的答案已經涵蓋爲什麼他們加入這個功能,爲什麼它是不適合的屬性總是會得到什麼設置有問題。在你自己的代碼中,你總是使用一個具有合適語義的中間屬性來綁定,並使用具有所需語義的內部屬性。我會將中間屬性稱爲「阻塞」屬性,因爲它會阻止吸氣劑到達您的內部屬性。

但是,如果您無法訪問要設置屬性的實體的源代碼,並且您想要舊的行爲,則可以使用轉換器。

這裏是一個阻塞轉換器狀態:

public class BlockingConverter : IValueConverter 
{ 
    public object lastValue; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return lastValue; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     lastValue = value; 
     return value; 
    } 
} 

,你可以用它爲你的例子是這樣的:

<Grid> 
    <Grid.Resources> 
     <local:BlockingConverter x:Key="blockingConverter" x:Shared="False"/> 
    </Grid.Resources> 
    <StackPanel> 
     <TextBox Text="{Binding TextProperty, Mode=OneWayToSource, Converter={StaticResource blockingConverter}}"/> 
     <Button Content="Click"/> 
    </StackPanel> 
</Grid> 

注意,因爲轉換器有一個狀態,你需要一個單獨的實例每次使用資源時,我們都可以使用資源上的x:Shared="False"屬性。

4

錯誤,當然。

如果它是一個「功能」,這是一個非常糟糕的一個...

似乎他們甚至在OneWayToSource模式的設定後添加的get()函數的調用()完成。 ..任何人都可以解釋爲什麼?

也,感謝指出了這一點,它說明了一個問題,因爲我升級我的項目.NET 4.0我曾和我不能直到現在解釋...

只是一個側面說明:我有最後通過使用依賴屬性解決了這個問題。

+0

我的猜測是爲了反映您在設置過程中可能應用的任何過濾,以便TextBox的內容實際上反映了「真正」設置的值。然後,OneWayToSource唯一不同的地方是它只會在應用set()之後調用get(),而不是在發送屬性更改通知時調用get()。 – 2011-02-02 15:46:40

+0

在一個側面說明中,一個以這種方式行爲的屬性(它暴露了一個getter,但get與設置的內容完全無關)是一個相當的病態屬性。這聽起來像你真正想要的是一個方法,但是打包爲一個屬性以允許綁定系統觸發該呼叫。這可能是值得研究創建一個自定義行爲,因爲這樣你就不必濫用財產製度。 – 2011-02-02 15:51:28

+0

@丹·布萊恩特:你在評論戴維的回答還是你在回答這個問題? :)我應該補充說,如果你刪除了getter,那麼每當`LostFocus`被引發時,`TextBox`都會一直是空白的。當然,這不可能是「OneWayToSource」綁定的理想方式,或者您認爲如何? – 2011-02-02 17:04:29

6

這確實是由設計。通常情況下,它不應該製造麻煩,但是我的意思是,你的財產執行至少是非常規的。吸氣和吸氣(吸氣)應該不會比得到和設置多得多,而且每個吸氣和吸氣應該與最後一組相一致。 (對不起,沒有這方面的資料,這正是我所在的所有開發團隊所稱的良好公民身份)。

在此處詳細瞭解功能的詳細信息:http://karlshifflett.wordpress.com/2009/05/27/wpf-4-0-data-binding-change-great-feature/

0

這是.NET 4.0中OneWayToSource綁定的期望行爲嗎?

是的。這是爲了讓開發人員能夠在不笨拙的轉換器的情況下改變提供的值。

它在3.5中的工作方式有什麼問題?

沒問題。它在3.5中的工作方式不允許更正提供的值。

在什麼情況下這種新行爲更好?

當您需要更正提供的值。如果你不需要它,那麼你應該寫出正確的屬性的getter和setter。

public string TextProperty 
{ 
    get; 
    set; 
} 

然而,我所看到的,不斷變化的UpdateSourceTrigger爲「的PropertyChanged」保留被重讀值(這樣你就可以離開舊財產申報):

<StackPanel> 
    <TextBox Text="{Binding TextProperty, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"/> 
    <Button/> 
</StackPanel> 

    private string m_textProperty; 
    public string TextProperty 
    { 
     get 
     { 
      return "Should not be used in OneWayToSource Binding"; 
     } 
     set 
     { 
      m_textProperty = value; 
     } 
    } 
2

這是很清楚的錯誤。似乎至少有人報告過一次。 https://connect.microsoft.com/VisualStudio/feedback/details/612444/onewaytosource-broken-in-net-4-0

我與許多其他人的同意,一個方法應該是單向的時期。

我的情況是複雜的和框架版本之間的變化具有一定功能給我帶來了真正的頭痛。

我有綁定到一個屬性文本框。我有一個轉換器,可以隨時更改格式。 EG:我在文本框中輸入EU5,屬性獲得EU005。我有綁定設置觸發屬性更改,因爲我需要在ViewModel內查找用戶類型。當我輸入時,新的實現改變了文本框的值。所以如果我想輸入EU512,我不能輕易地改變文本框的內容。

我已經嘗試了許多事情 - 顯式綁定(您決定何時更新和以何種方式。)這有同樣的問題。如果我說的是UpdateSource,那麼它也會重新讀取該屬性並更改目標。

我試過OneWayToSource並有同樣的問題。我發現沒有辦法解決這個問題,而不會對我的虛擬機進行惱人的更改。唯一的另一種方式是刪除綁定在這個領域,並開始射擊事件將是可怕的。

如果MS使綁定的行爲按照邏輯命名,那麼我的問題就會消失。即使是綁定選項退出.net4實現並且表現爲3.5的屬性也適用於我。

任何人對我有什麼建議可以解決這個問題?

0

我有一個雙向綁定這個問題的變化。我意識到這與所討論的問題不完全相同,但是這個答案在搜索時出現了,並且導致了我的解決方案。希望有人發現它有幫助。

我的解決方案阻止重新讀取支持屬性,但會更新UI時,由其他來源更改。我在Rick Sladkey的答案中將我的解決方案基於阻塞轉換器。

它只是將一個檢查添加到轉換,以查看lastValue字段是否將轉換爲相同的後備存儲值。如果不是,則後備存儲值必須從其他源更改,並且應更新UI。

public class MyConverter : IValueConverter 
{ 
    public object lastValue; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (LastValue != null && MyConvertBack(LastValue).Equals(value)) 
      return lastValue; 
     else 
      return MyConvert(value); 

    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     lastValue = value; 
     return MyConvertBack(value); 
    } 

    private object MyConvertBack(Object value) 
    { 
     //Conversion Code Here 
    } 

    private object MyConvert(Object value) 
    { 
     //Conversion Code Here 
    } 
} 

在我的這個特殊的用例中,我有一個長度和尺寸後綴存儲在一個文本框(10米,100毫米等)。轉換器將其解析爲double值或添加後綴(取決於轉換方向)。如果沒有轉換器,它會在文本框的每次更新中添加一個後綴。嘗試鍵入'10'會導致'1m0',因爲轉換器會在第一次擊鍵後運行。

相關問題