1

描述: 我有一個自定義的內容控件,我試圖通過依賴屬性啓用一些外部設置。基本上它是一個有兩個網格行的裝飾面板,上面一個是標題,下面是內容(通過ContentPresenter)。模板綁定RowDefinition.Height在ContentControl中被忽略

有被綁定到該模板(通過TemplateBinding),HeaderHeightTextSizeHeader(它們中的每一個具有適當類型的其依賴屬性)3項。

問題: 雖然兩個綁定工作完全(甚至在設計時),第三個則沒有。 FontSize="{TemplateBinding TextSize}"Text="{TemplateBinding Header}"綁定工作,但<RowDefinition Height="{TemplateBinding HeaderHeight}" />不起作用

無論我將HeaderHeight屬性設置爲哪個值,網格都將行高分爲50/50。它甚至不採用DP元數據的默認值。

問題: 這種情況下有什麼問題?爲什麼其他兩個綁定工作沒有問題,而這個綁定的行爲就好像根本沒有綁定一樣?

注: 如果我在構造函數中設置DataContext = this{Binding HeaderHeight}取代{TemplateBinding HeaderHeight},問題消失,它按預期工作。但我想知道爲什麼我不需要用其他綁定來做同樣的事情來使它們工作。

XAML(主題/ Generic.xaml):

<Style TargetType="local:KaiPanel"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="local:KaiPanel"> 
       <Grid x:Name="LayoutRoot"> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="{TemplateBinding HeaderHeight}" /> 
         <RowDefinition /> 
        </Grid.RowDefinitions> 

        <Grid Grid.Row="0"> 
         <Border> 
          <TextBlock FontSize="{TemplateBinding TextSize}" 
             Text="{TemplateBinding Header}" /> 
         </Border> 
        </Grid> 

        <Grid Grid.Row="1"> 
         <Border> 
          <ContentPresenter /> 
         </Border> 
        </Grid> 

       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

內容控制(C#):

public class KaiPanel : ContentControl 
{ 
    public KaiPanel() 
    { 
     this.DefaultStyleKey = typeof(KaiPanel); 
    } 

    public static readonly DependencyProperty TextSizeProperty = 
     DependencyProperty.Register("TextSize", typeof(double), typeof(KaiPanel), new PropertyMetadata(15.0)); 

    public double TextSize 
    { 
     get { return (double)GetValue(TextSizeProperty); } 
     set { SetValue(TextSizeProperty, value); } 
    } 

    public static readonly DependencyProperty HeaderProperty = 
     DependencyProperty.Register("Header", typeof(String), typeof(KaiPanel), new PropertyMetadata("")); 

    public String Header 
    { 
     get { return (String)GetValue(HeaderProperty); } 
     set { SetValue(HeaderProperty, value); } 
    } 

    public static readonly DependencyProperty HeaderHeightProperty = 
     DependencyProperty.Register("HeaderHeight", typeof(GridLength), typeof(KaiPanel), new PropertyMetadata(new GridLength(40))); 

    public GridLength HeaderHeight 
    { 
     get { return (GridLength)GetValue(HeaderHeightProperty); } 
     set { SetValue(HeaderHeightProperty, value); } 
    } 
} 

自定義控制使用(XAML):

<UserControl ...> 

    <Grid x:Name="LayoutRoot"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="150" /> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 

     <StackPanel x:Name="buttonsStackPanel" Grid.Column="0" VerticalAlignment="Center"> 
      <!-- Some buttons here --> 
     </StackPanel> 

     <Grid Grid.Column="1"> 
      <controls:KaiPanel x:Name="contentPanel"> 
       <navigation:Frame x:Name="contentFrame" Source="KP"> 
        <navigation:Frame.UriMapper> 
         <uriMapper:UriMapper> 
          <uriMapper:UriMapping Uri="KP" MappedUri="/Views/Kornelijepetak.xaml" /> 
          <uriMapper:UriMapping Uri="KAI" MappedUri="/Views/KaiNetwork.xaml" /> 
         </uriMapper:UriMapper> 
        </navigation:Frame.UriMapper> 
       </navigation:Frame> 
      </controls:KaiPanel> 
     </Grid> 
    </Grid> 
</UserControl> 
+0

你有沒有Xaml實際使用KaiPanel的例子,所以我們可以重現這個問題?到目前爲止,所有顯示的內容看起來都不錯,但只需要一點細節就可以打破某些內容 –

+0

@我更新了代碼,但沒關係。即使您放置一個標籤,它也不起作用。它應該採用DP的默認值,但不是。試圖在內部放置不同的內容,但不重要 - 它總是表現相同:50/50。 –

回答

0

不幸的是,看起來你試圖做的事情不僅僅需要單一的數據綁定。 RowDefinition不是FrameworkElement的子類,它不符合MSDN Silverlight data binding documentation中指定的任何其他條件,因此它不能用作綁定的目標。

你想做什麼是可能的,但不幸的是它涉及更多的代碼。

首先,爲主柵格添加一個字段(我稱之爲mainGrid)到KaiPanel類。然後,覆蓋OnApplyTemplate方法在這個類抓住從模板來Grid,並保持在你的mainGrid領域對它的引用:

public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 
     mainGrid = GetTemplateChild("LayoutRoot") as Grid; 
     SetHeaderRowHeight(); 
    } 

這調用更新網格的第一行的高度的方法。該方法如下:

private void SetHeaderRowHeight() 
    { 
     if (mainGrid != null) 
     { 
      mainGrid.RowDefinitions[0].Height = HeaderHeight; 
     } 
    } 

我承認我不是100%肯定DPS的設置後OnApplyTemplate被調用。看起來情況就是這樣(一個快速測試似乎證實了這一點),但我能找到支持這一點的是this post on the Silverlight forums。如果您發現情況並非如此,您需要在HeaderHeight DP上註冊一個PropertyChangedCallback,該調用也將調用此方法SetHeaderRowHeight。請參閱http://forums.silverlight.net/forums/t/76992.aspx#183089

+0

你說它不能在綁定中使用,但它在普通綁定(而不是TemplateBinding)中工作。再次檢查我的註釋。如果DataContext =這是在一個構造函數中設置的,並且在模板中,如果我設置了{Binding HeaderHeight}而不是{TemplateBinding HeaderHeight},那麼它就起作用了。非常奇怪的行爲。我有另一個控件,甚至與TemplateBinding一起工作,這使得這更奇怪。 –

+0

更正:我現在看着我的另一個控件。它不適用於模板綁定,但它使用普通綁定(將DataContext設置爲控件本身)。 –