2011-04-22 50 views
1

我想跟隨與C#和XAML的MVVM設計範例。我遇到了嵌套用戶控件的麻煩。我試圖將嵌套用戶控件上的元素綁定到ViewModel中的一個值(它通過DataContext屬性綁定到視圖)。外部和嵌套用戶控件都使用相同的ViewModel。DependencyProperty綁定模式twoway但propertychangedeventhandler爲空

它部分按原樣工作,但只能從ViewModel單向更改爲嵌套用戶控件。我需要在嵌套用戶控件中進行的更改傳播回ViewModel。

與XAML主視圖開始,我有:

<UserControl> 

    <!-- ... --> 

    <UserControl.DataContext> 
     <local:MyViewModel x:Name="myViewModel" /> 
    </UserControl.DataContext> 

    <!-- ... --> 

    <local:NestedUserControl 
     x:Name="nestedUserControl" 
     CustomNestedValue="{Binding Path=CustomValue, ElementName=myViewModel, Mode=TwoWay}" /> 

</UserControl> 

在該視圖模型的C#代碼:

// Constructor 
public MyViewModel() 
{ 
    CustomValue = true; 
} 

private bool _customValue; 
public bool CustomValue 
{ 
    get { return _customValue; } 
    set 
    { 
     if (_customValue != value) 
     { 
      _customValue = value; 
      RaisePropertyChanged ("CustomValue"); 
     } 
    } 
} 

而在NestedUserControl後面的代碼,我有:

public static readonly DependencyProperty CustomNestedValueProperty = 
    DependencyProperty.Register (
     "CustomNestedValue", 
     typeof (bool), 
     typeof (NestedUserControl), 
     new FrameworkPropertyMetatdata 
     { 
     BindsTwoWayByDefault = true, 
     PropertyChangedCallback = 
      new PropertyChangedCallback (CustomNestedValueChangedCallback) 
     }); 

public bool CustomNestedValue 
{ 
    get { return (bool) GetValue (CustomNestedValueProperty); } 
    set { SetValue (CustomNestedValueProperty, value); } 
} 

protected static void CustomNestedValueChangedCallback (
    DependencyObject Source, 
    DependencyPropertyChangedEventArgs e) 
{ 
    bool value = (bool) e.NewValue; 
    NestedUserControl control = source as NestedUserControl; 
    control.OnCustomValueChange (value); 
} 

public void OnCustomValueChange (bool value) 
{ 
    RaisePropertyChanged ("CustomNestedValue"); 

    // Do other stuff ... 
} 

// This function is where the nested user control gets direct 
// interactions from the user which cause the dependency 
// property to change. When this event occurs, the change needs 
// to be communicated back up to the view model. 
private void _onPreviewMouseDown (object sender, MouseButtonEventArgs e) 
{ 
    CustomNestedValue = !CustomNestedValue; 
} 

[注意:不僅在設置綁定模式爲TwoWay時在XAML中綁定,但我試圖使這是上面代碼中DependencyProperty的默認行爲。沒有運氣。]

兩個後面的嵌套用戶控制和視圖模型代碼的代碼包含以下PropertyChangedEventHandler事件/反應,這是必要的INotifyPropertyChanged接口。據我所知,這是XAML元素和ViewModel之間的綁定如何保持同步。

public event PropertyChangedEventHandler PropertyChanged; 

protected void RaisePropertyChanged(string propertyName) 
{ 
    try 
    { 
     if (this.PropertyChanged != null) 
     this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    catch (Exception e) 
    { 
     // ... 
    } 
} 

當我運行代碼,每當RaisePropertyChanged函數被調用爲NestedUserControl,該PropertyChanged事件總是。這只是嵌套的usercontrol的一個問題,而不是外部的問題。不應該通過綁定機制自動設置此事件嗎?

我一直在掙扎着這幾天,現在無濟於事。任何幫助將非常感激。謝謝!

回答

2

綁定到DependencyObject的操作不使用接口INotifyPropertyChanged。實際上,如果您在NestedUserControlCustomNestedValue屬性的getter或setter中設置斷點,則會發現在XAML中綁定時它將永遠不會命中。實質上,INotifyPropertyChanged是一種實現約束而不從DependencyObject降序的方式。

MyViewModel.CustomValue綁定到NestedUserControl,綁定代碼調用(在僞代碼):

NestedUserControl.SetBinding(binding, NestedUserControl.CustomNestedValueProperty) 

INotifyPropertyChanged.PropertyChanged事件是從來沒有註冊,將保持空。但是,這並不一定回答爲什麼該值不返回ViewModel。

無論如何,你可以刪除一些運動件,與

public static readonly DependencyProperty CustomNestedValueProperty = 
    DependencyProperty.Register("CustomNestedValue", 
           typeof (bool), 
           typeof (NestedUserControl), 
           null); 

public bool CustomNestedValue 
{ 
    get { return (bool) GetValue (CustomNestedValueProperty); } 
    set { SetValue (CustomNestedValueProperty, value); } 
} 

那怎麼我的大多數DependencyProperties的寫入和他們不支持TwoWay結合去。

+0

你是我的救星!我太累了。我從嵌套控件中刪除了INotifyPropertyChanged接口,它工作。非常感謝。 – RobotNerd 2011-04-22 03:15:28

相關問題