2016-05-12 64 views
3

我想創建自定義控件添加屬性Info和InfoTemplate爲例。
我使用ContetnPresenter爲Info屬性定義generic.xaml中的ControlTemplate。
當我不使用InfoTemplate時它工作正常,但是當我應用ItemTemplate時,內容被表示爲類名字符串。應用於GroupBox的相同模板按照預期工作。我錯了什麼?我在OnApplyTemplate中需要一些額外的代碼?
貝婁打印屏幕我的應用程序和來源。紅色邊框是一個GroupBox,藍色是我的控制。綠色邊框是DataTemplate的一部分。爲什麼DataTemplate會返回類名而不是控件?

App print-screen

編輯: 爲了測試我創建的類繼承MyGroupBox形式分組框和覆蓋方法OnHeaderChanged

public class MyGroupBox : GroupBox 
{ 
    protected override void OnHeaderChanged(object oldHeader, object newHeader) 
    { 
     //base.OnHeaderChanged(oldHeader, newHeader); 
    } 
} 

在這種情況下GroupBox.Heder行爲像我MyCustomControl和顯示文本,而不是控制。所以問題是:我應該在自己的控制事件中實施我想要的工作?


MyCustomControl.cs

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

namespace WpfApplication7 
{ 

    public class MyCustomControl : ContentControl 
    { 
     static MyCustomControl() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl))); 
     } 

     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 
     } 

     public object Info 
     { 
      get { return (object)GetValue(InfoProperty); } 
      set { SetValue(InfoProperty, value); } 
     } 

     public DataTemplate InfoTemplate 
     { 
      get { return (DataTemplate)GetValue(InfoTemplateProperty); } 
      set { SetValue(InfoTemplateProperty, value); } 
     } 

     public static readonly DependencyProperty InfoProperty = 
      DependencyProperty.Register(nameof(Info), typeof(object), typeof(MyCustomControl), new PropertyMetadata(null)); 

     public static readonly DependencyProperty InfoTemplateProperty = 
      DependencyProperty.Register(nameof(InfoTemplate), typeof(DataTemplate), typeof(MyCustomControl), new PropertyMetadata(null)); 
    } 
} 

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:WpfApplication7"> 

    <Style TargetType="{x:Type local:MyCustomControl}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type local:MyCustomControl}"> 
        <StackPanel> 

         <TextBlock FontWeight="Bold">Info</TextBlock> 
         <ContentPresenter ContentSource="Info"/> 

         <TextBlock FontWeight="Bold">Content</TextBlock> 
         <ContentPresenter/> 
        </StackPanel> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

MainWindow.xml

<Window x:Class="WpfApplication7.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfApplication7" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     DATA_CONTEXT 
    </Window.DataContext> 
    <Window.Resources> 
     <DataTemplate x:Key="dataTemplate"> 
      <Border BorderBrush="Green" BorderThickness="5"> 
       <ContentPresenter Content="{Binding}"/> 
      </Border> 
     </DataTemplate> 
    </Window.Resources> 
    <StackPanel> 

     <Border BorderBrush="Red" BorderThickness="4"> 
      <GroupBox HeaderTemplate="{StaticResource dataTemplate}"> 
       <GroupBox.Header> 
        <TextBlock Text="{Binding}"/> 
       </GroupBox.Header> 
      </GroupBox> 
     </Border> 

     <Border BorderBrush="Blue" BorderThickness="4"> 
      <local:MyCustomControl InfoTemplate="{StaticResource dataTemplate}"> 
       <local:MyCustomControl.Info> 
        <TextBlock Text="{Binding}"/> 
       </local:MyCustomControl.Info> 

       My content 
      </local:MyCustomControl> 
     </Border> 
    </StackPanel> 
</Window> 

MainWindow.xaml.cs

using System.Collections.Generic; 
using System.Windows; 


namespace WpfApplication7 
{ 

    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

回答

2

所以報廢我的答案,現在我有一個更好的瞭解所請求內容的重新開始。這裏的想法是基本上重新創建一個像控件一樣的自定義GroupBox。問題是自定義控件中的Info屬性的DataContext(基本上是GroupBoxHeader屬性)不會像自定義控件本身的DataContext一樣出現,就像使用GroupBox時一樣。

所以問題是您設置爲Info屬性的UI塊不會添加爲控件的邏輯子項,因此它不會以繼承DataContext的方式添加在GroupBox中使用相同的代碼。要做到這一點只需要更新您的自定義的控件類以下幾點:

public class MyCustomControl : ContentControl 
    { 
     static MyCustomControl() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl))); 
     } 

     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 
     } 

     public object Info 
     { 
      get { return (object)GetValue(InfoProperty); } 
      set { SetValue(InfoProperty, value); } 
     } 

     public DataTemplate InfoTemplate 
     { 
      get { return (DataTemplate)GetValue(InfoTemplateProperty); } 
      set { SetValue(InfoTemplateProperty, value); } 
     } 

     public static readonly DependencyProperty InfoProperty = 
      DependencyProperty.Register(nameof(Info), typeof(object), typeof(MyCustomControl), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(MyCustomControl.OnHeaderChanged))); 

     private static void OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var obj = (MyCustomControl)d; 
      obj.RemoveLogicalChild(e.OldValue); 
      obj.AddLogicalChild(e.NewValue); 
     } 

     public static readonly DependencyProperty InfoTemplateProperty = 
      DependencyProperty.Register(nameof(InfoTemplate), typeof(DataTemplate), typeof(MyCustomControl), new PropertyMetadata(null)); 
    } 

這將解決這個問題,但是,應該說,它可能會被清潔剛剛從HeaderedContentControl派生,而不是從ContentControlHeaderedContentControl已經爲您設置了所有這些設置,並且已經有一個HeaderHeaderTemplate,您可以使用它們代替您的InfoInfoTemplate屬性,從而爲您節省一些代碼。

如果你想在不打亂邏輯孩子等的情況下工作,你可以更新你設置Info的UI塊中的綁定,並讓它使用RelativeSource來搜索自定義控件祖先,然後有一個「DataContext」的路徑,這將手動覆蓋整個問題,但你必須記住每次都這樣做。

我的選擇將是這將是最適合你剛從HeaderedContentControl派生,它看起來像應該擁有所有的功能,你正在尋找已經烤。

+0

這並不完全工作。如果我確實喜歡你寫,那麼Info TextBlock上沒有綠色邊框。當我沒有設置InfoTemplate時,這種行爲是相同的。我的generic.xaml類似於Blend中生成的GroupBox的ControlTemplate。 – siwydym67

+0

如果你想保留綠色邊框,那麼你應該將ContentTemplate =「{TemplateBinding InfoTemplate}」'添加到我包含在我的答案中的ContentPresenter行。您的ContentSource之前(與其他屬性一起)設置此項,正如我在我的答案中引用的文章中所解釋的。 –

+0

我知道ContentSource的工作原理。你是否嘗試用你的更改運行我的代碼?這不適合我,或者我做錯了什麼。 – siwydym67

相關問題