2014-02-12 28 views
2

我創建了一個具有兩個TemplateParts的CustomControl。CustomControl與TemplateParts

using System; 
using System.Windows; 
using System.Windows.Controls; 

namespace WpfCustomControlLibrary1 
{ 
    [TemplatePart(Name = "PART_ControlsLayer", Type = typeof (ContentPresenter))] 
    [TemplatePart(Name = "PART_DisplayLayer", Type = typeof (ContentPresenter))] 
    public class CustomControl1 : Control 
    { 
     public static readonly DependencyProperty ControlsLayerProperty = 
      DependencyProperty.Register("ControlsLayer", typeof (object), typeof (CustomControl1), 
      new UIPropertyMetadata(null)); 

     public static readonly DependencyProperty DisplayLayerProperty = 
      DependencyProperty.Register("DisplayLayer", typeof (object), typeof (CustomControl1), 
      new UIPropertyMetadata(null)); 

     private ContentPresenter partControlsLayer; 
     private ContentPresenter partDisplayLayer; 

     static CustomControl1() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof (CustomControl1), 
       new FrameworkPropertyMetadata(typeof (CustomControl1))); 
     } 


     public object ControlsLayer 
     { 
      get { return GetValue(ControlsLayerProperty); } 
      set { SetValue(ControlsLayerProperty, value); } 
     } 

     public object DisplayLayer 
     { 
      get { return GetValue(DisplayLayerProperty); } 
      set { SetValue(DisplayLayerProperty, value); } 
     } 

     public override void OnApplyTemplate() 
     { 
      ApplyTemplate(); 

      partControlsLayer = GetTemplateChild("PART_ControlsLayer") as ContentPresenter; 


      partDisplayLayer = GetTemplateChild("PART_DisplayLayer") as ContentPresenter; 

      if (partControlsLayer == null || partDisplayLayer == null) 
      { 
       throw new NullReferenceException("Template parts not available"); 
      } 
     } 
    } 
} 

在Generic.xaml我所定義的的ControlTemplate和默認設定器用於DisplayLayer中的(所述TemplateParts之一)。最後,我將其設置爲CustomControl1的模板。

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfCustomControlLibrary1"> 

    <Style TargetType="{x:Type local:CustomControl1}"> 
     <Style.Resources> 
      <ControlTemplate x:Key="DefaulTemplate" TargetType="{x:Type local:CustomControl1}"> 
       <Grid> 
        <ContentPresenter x:Name="PART_ControlsLayer" 
              Content="{TemplateBinding ControlsLayer}" /> 
        <ContentPresenter x:Name="PART_DisplayLayer" 
              Content="{TemplateBinding DisplayLayer}" /> 
       </Grid> 
      </ControlTemplate> 
     </Style.Resources> 

     <Setter Property="DisplayLayer"> 
      <Setter.Value> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
        </Grid.RowDefinitions> 
        <Label Grid.Row="0" Content="{Binding FunctionName, FallbackValue=Functionname}" /> 
        <TextBlock Grid.Row="1" Text="{Binding DisplayValue, FallbackValue=0.0dB}" Foreground="Lime" 
           Background="Black" /> 
       </Grid> 
      </Setter.Value> 
     </Setter> 
     <Setter Property="Template" Value="{StaticResource DefaulTemplate}"/> 
    </Style> 

    <Style TargetType="{x:Type local:CustomControl2}" BasedOn="{StaticResource {x:Type local:CustomControl1}}" /> 
</ResourceDictionary> 

現在我創建一個CustomControl2 BasedOn CustomControl1。

using System.Windows; 

namespace WpfCustomControlLibrary1 
{ 
    public class CustomControl2 : CustomControl1 
    { 
     static CustomControl2() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl2), new FrameworkPropertyMetadata(typeof(CustomControl2))); 
     } 
    } 
} 

然後我把兩個控件放在一個WpfWindow上。

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:wpfCustomControlLibrary1="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 
     <wpfCustomControlLibrary1:CustomControl1 Grid.Row="0"/> 

     <wpfCustomControlLibrary1:CustomControl2 Grid.Row="1"/> 
    </Grid> 
</Window> 

問題是我只能在第二個控件上看到Defaulttemplate。我找不到解決方法,請幫忙。

@ gomi42 - 如果我改變Generic.xaml這樣:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfCustomControlLibrary1"> 

    <Style x:Key="BaseStyle" TargetType="{x:Type local:CustomControl1}"> 
     <Style.Resources> 
      <ControlTemplate x:Key="DefaulTemplate" TargetType="{x:Type local:CustomControl1}"> 
       <Grid> 
        <ContentPresenter x:Name="PART_ControlsLayer" 
              Content="{TemplateBinding ControlsLayer}" /> 
        <ContentPresenter x:Name="PART_DisplayLayer" 
              Content="{TemplateBinding DisplayLayer}" /> 
       </Grid> 
      </ControlTemplate> 
     </Style.Resources> 

     <Setter Property="Template" Value="{StaticResource DefaulTemplate}"/> 

     <Setter Property="DisplayLayer"> 
      <Setter.Value> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
        </Grid.RowDefinitions> 
        <Label Grid.Row="0" Content="{Binding FunctionName, FallbackValue=Functionname}" /> 
        <TextBlock Grid.Row="1" Text="{Binding DisplayValue, FallbackValue=0.0dB}" Foreground="Lime" 
           Background="Black" /> 
       </Grid> 
      </Setter.Value> 
     </Setter> 
    </Style> 

    <Style TargetType="{x:Type local:CustomControl1}" BasedOn="{StaticResource BaseStyle}" /> 

    <Style TargetType="{x:Type local:CustomControl2}" BasedOn="{StaticResource BaseStyle}" /> 
</ResourceDictionary> 

沒有什麼變化!僅在第二個控件中仍然可見。

回答

0

我發現它!

這是導致問題的DependencyProperty。我實施的CustomControl就像本網站上的例子: http://www.kunal-chowdhury.com/2011/04/how-to-implement-template-binding-in.html

我該怎麼說這個例子是錯誤的!

這是它是如何工作的。

首先CustomControl.cs

using System; 
using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using System.Windows; 
using System.Windows.Controls; 
using WpfCustomControlLibrary1.Annotations; 

namespace WpfCustomControlLibrary1 
{ 
    [TemplatePart(Name = "PART_ControlsLayer", Type = typeof (Grid))] 
    [TemplatePart(Name = "PART_DisplayLayer", Type = typeof(ContentControl))] 
    public class CustomControl1 : Control 
    { 
     private Grid partControlsLayer; 
     private ContentControl partDisplayLayer; 

     static CustomControl1() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof (CustomControl1), 
       new FrameworkPropertyMetadata(typeof (CustomControl1))); 
     } 

     public CustomControl1() 
     { 
      DataContext = this; 
     } 


     public override void OnApplyTemplate() 
     { 
      ApplyTemplate(); 

      partControlsLayer = GetTemplateChild("PART_ControlsLayer") as Grid; 


      partDisplayLayer = GetTemplateChild("PART_DisplayLayer") as ContentControl; 

      if (partControlsLayer == null || partDisplayLayer == null) 
      { 
       //throw new NullReferenceException("Template parts not available"); 
      } 
     } 
    } 
} 

然後Generic.xaml

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfCustomControlLibrary1"> 

    <Style x:Key="DefaultTemplate" TargetType="{x:Type ContentControl}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type ContentControl}"> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition /> 
          <RowDefinition /> 
         </Grid.RowDefinitions> 
         <Label Grid.Row="0" Content="{Binding FunctionName, FallbackValue=Functionname}" /> 
         <TextBlock Grid.Row="1" Text="{Binding DisplayValue, FallbackValue=0.0dB}" Foreground="Lime" 
            Background="Black" /> 
        </Grid> 

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


    <Style TargetType="{x:Type local:CustomControl1}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition /> 
          <RowDefinition /> 
         </Grid.RowDefinitions> 
         <ContentControl x:Name="PART_DisplayLayer" Style="{StaticResource DefaultTemplate}" /> 
         <Grid x:Name="PART_ControlsLayer" Grid.Row="1"> 
          <Grid.RowDefinitions> 
           <RowDefinition /> 
           <RowDefinition /> 
          </Grid.RowDefinitions> 
          <Button Grid.Row="0" Content="{Binding FunctionName, FallbackValue=Functionname}" /> 
          <Button Grid.Row="1" Content="{Binding DisplayValue, FallbackValue=0.5dB}" /> 
         </Grid> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

    <Style TargetType="{x:Type local:CustomControl2}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition /> 
          <RowDefinition /> 
         </Grid.RowDefinitions> 
         <ContentControl x:Name="PART_DisplayLayer" Style="{StaticResource DefaultTemplate}" /> 
         <Grid x:Name="PART_ControlsLayer" Grid.Row="1"> 
          <Grid.RowDefinitions> 
           <RowDefinition /> 
           <RowDefinition /> 
          </Grid.RowDefinitions> 
          <Button Grid.Row="0" Content="Depp" /> 
          <Button Grid.Row="1" Content="{Binding DisplayValue, FallbackValue=1.0dB}" /> 
         </Grid> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

CustomControl2.cs作爲派生類

using System.Windows; 

namespace WpfCustomControlLibrary1 
{ 
    public class CustomControl2 : CustomControl1 
    { 
     static CustomControl2() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl2), new FrameworkPropertyMetadata(typeof(CustomControl2))); 
     } 

     public CustomControl2() 
     { 
      DataContext = this; 
     } 
    } 
} 

主窗口仍然是相同的。

這是行不通的,因爲沒有內容是靜態的。

0

您創建的樣式只適用於CustomControl1因爲這樣:

<Style TargetType="{x:Type local:CustomControl1}"> 
... 

您需要創建CustomControl2例如新樣式通過繼承:

<Style x:Key="MyBase" TargetType="{x:Type local:CustomControl1}"> 
... 
</Style> 

<Style TargetType="{x:Type local:CustomControl1}" BasedOn={StaticResource MyBase} /> 
<Style TargetType="{x:Type local:CustomControl2}" BasedOn={StaticResource MyBase} /> 
+0

我不明白。如果我這樣做,我應該在哪裏放置模板屬性的setter? – GreenEyedAndy

+0

看到我編輯的問題 – GreenEyedAndy

+1

看起來好像是靜態的,所以只能在使用這種風格的最後一個控件上看到。嘗試在MainWindow中添加另一行並添加第三個控件(例如另一個CustomControl2)。它又是顯示內容的最後一個控件。 – GreenEyedAndy