2012-01-05 38 views
3

視圖模型:依賴屬性綁定和更新到自定義控件 - 它更新,但顯然不是兩種方式?

public class MyViewModel : INotifyPropertyChanged 
{ 
    public string MyText { ... } 
} 

XAML:

<my:MySpecialTextBox Text="{Binding MyText}" /> 

自定義控件:

public class MySpecialTextBox : TextBox 
{ 
    static MySpecialTextBox() 
    { 
     TextProperty.OverrideMetadata(typeof(MySpecialTextBox), 
      new FrameworkPropertyMetadata 
      { 
       BindsTwoWayByDefault = true, 
       DefaultValue = string.empty, 
       PropertyChangedCallback = OnTextPropertyChanged 
      }); 
    } 

    private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var control = d as MySpecialTextBox; 

     if (control != null) 
     { 
      control.Text = SomeAdjustedValue((string)e.NewValue); 
     } 
    } 
} 

的問題是,雖然DependencyProperty的自定義控制並調整不當,它不更新ViewModel。我意識到這似乎好像它應該是CoerceValueCallback由於SomeAdjustedValue的命名,但Coercion不會更改ViewModel值。我似乎無法更新我的ViewModel中的值,如果它是OnTextPropertyChanged回調的觸發器開始...我做了一個調試跟蹤,它不會再次通過ViewModel使用新值。不知道在這裏做什麼來解決這個問題。

+0

只是爲了確保我能理解 - 您期待通過PropertyChanged通知提升到UI的ViewModel的更改來更新UI,然後由於綁定回調,隨後將路由回ViewModel? – 2012-01-05 16:04:43

回答

0

在FrameworkPropertyMetadata中,可以使用不同的構造函數。使用FrameworkPropertyMetadataOptions參數。 FrameworkPropertyMetadataOptions.BindsTwoWayByDefault選項將默認打開雙向綁定,否則它只是一種方式。

編輯:所以你做了,當我生病時,我應該停止嘗試回答問題。

+0

嗯,我確實將BindsTwoWayByDefault設置爲true。 – michael 2012-01-05 16:12:27

0

免責聲明 - 這聽起來像是應該存在於ViewModel內部的邏輯,而不是在UI綁定中。這就是說,如果你這樣做,我認爲你需要首先檢查「調整值」是否與已經提供的值不同(爲了避免無限循環),然後使用DependencyProperty.SetValue來設置控件上的依賴項屬性的值,而不僅僅是設置Text屬性。

+0

這不起作用...它再次在我的自定義控件上設置值,但它不更新視圖模型。 – michael 2012-01-05 16:41:32

+0

SetValue()取代綁定;請改用SetCurrentValue()。 – 2012-04-26 00:17:59

0

TextBox.Text是一個綁定,並且您正在用OnTextPropertyChanged中的字符串值替換該綁定,因此該屬性不再綁定到您的數據源。

我認爲你需要獲得綁定TextBox.Text並更新源代碼,但是我不會推薦這麼做,因爲你會將業務邏輯層與UI層混合在一起。

如果您只想顯示一些自定義格式,我會在Converter中執行此操作,以免它實際上更改您的數據源的值。如果你想改變實際的數據源值,我會這樣做與ViewModel的PropertyChanged事件

+0

請參閱下面的答案 - 使用.NET 4,現在可以調用SetCurrentValue(dp,value)並設置該值而不影響綁定。 – 2012-04-26 00:17:42

0

你試試這個嗎?

private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var control = d as MySpecialTextBox; 

    if (control != null) 
    { 
     control.SetCurrentValue(TextBox.TextProperty, SomeAdjustedValue((string)e.NewValue)); 
    } 
} 

的SetCurrentValue()方法確保結合被保留,其中一個簡單的SetValue()是,如果你使用Text屬性setter將消除任何約束力什麼是引擎蓋下調用。

+0

請注意,您可能還需要設置一些成員布爾標誌,例如當您調用SetCurrentValue()時,「ignoreTextPropertyChangedEvent」;否則你可能會陷入無限循環。 – 2012-04-26 00:19:55

相關問題