[WPF]UserControl.DataContext與調用端的 依賴關係

  • 6681
  • 0
  • 2013-07-26

[WPF]UserControl.DataContext 繼承關係

    參考:http://www.codeproject.com/Articles/325911/A-Simple-Pattern-for-Creating-Re-useable-UserContr

 

    此範例(及參考網頁)以UserControl為範例,說明當在MainPage(主頁)調用時,UserControl.DataContext 依賴關係。

 

    UserControl.DataContext 會是暴露(public)的,若找不到參考的DataContext依賴關係會向上一直到找到為止(至最上層MainPage的DataContext)。

 

再補充一種狀況:

情境:若UserControl內的依賴屬性要參考本身的DataContext(ViewModel),而不是繼承父類 。

錯誤代碼如下:


	
//UserControl.xaml
<UserControl x:Class="UserControlExample.FieldUserControl" ...> 
     <StackPanel Orientation="Horizontal" > 
       <!--Control Putting and Do Bind-->
     </StackPanel> 
</UserControl>
//UserControlView .xaml.cs
public FieldUserControl()
{
 InitializeComponent(); 
 this.DataContext =new FieldViewModel(); 
} 
 #region Label DP
 
 /// <span class="code-SummaryComment"><summary>
 </span>  /// Gets or sets the Label which is displayed next to the field
 /// <span class="code-SummaryComment"></summary>
 </span> 
 public String Label
  {
    get { return (String)GetValue(LabelProperty); }
    set { SetValue(LabelProperty, value); }
  }
 
  /// <span class="code-SummaryComment"><summary>
  </span>  /// Identified the Label dependency property
  /// <span class="code-SummaryComment"></summary>
  </span>  
   public static readonly DependencyProperty LabelProperty =
      DependencyProperty.Register("Label", typeof(string),
        typeof(FieldUserControl), new PropertyMetadata(""));
 
  #endregion

       
調用代碼如下:
<MainPage….>
<Grid>
  <StackPanel Orientation="Vertical"
              HorizontalAlignment="Left"
              Margin="10">
    <local:FieldUserControl VerticalAlignment="Top"
                            Label="Height:"
                            Value="{Binding Height}"/>
  </StackPanel>
</Grid>
</MainPage>

 

  上述有說到UserControl.DataContext 是暴露的,當在MainPage內並無設定UserControl.DataContext將
造成UserControl.DataContext被父類覆蓋(繼承父類)。

 

解法:

//UserControl.xaml
<UserControl x:Class="UserControlExample.FieldUserControl"
    ...>
  <StackPanel Orientation="Horizontal"
              x:Name="LayoutRoot">
    ...
  </StackPanel>
</UserControl>

 

//UserControl.xaml.cs

public FieldUserControl()

{
  InitializeComponent();
 
  LayoutRoot.DataContext = new FieldViewModel();
}

 

       為什麼LayoutRoot.DataContext = new FieldViewModel();就不會造成向上繼承。因為它封閉在FieldUserControl內,並不直接暴露於外面,將不會直接受最上層父類影響;然而UserControl .DataContext是暴露在FieldUserControl外層,若調用的View(MainPage)沒給值會自動繼承父類模板的依賴屬性,看一下調用代碼即可發現,並沒賦予FieldUserControl.DataContext值。

 

此視覺樹,是在說明DataContext 的引響範圍。

DataContext

1.藍色部分:MainPage將會一直引響到FieldUserControl所暴露的依賴屬性,只要控件在此被調用,並且調用端(MainPage)沒給予UserControl的依賴屬性綁定值,則該UserControl的依賴屬性將自動繼承父類屬性,這說明了 若再UserControl的建構子內寫上this.DataContext =new ViewModel()是無意義的。

2.綠色部分:綠色部分為FieldUserControl封閉的部分,裡面的屬性將不直接受最上端調用者影響,但一樣會繼承FieldUserControl的依賴屬性。但是若在StackPanel內寫上StackPanelName(自訂義).DataContext = new ViewModel() ,將無視FieldUserControl.DataContext影響。

 

By-藍小伙