为什么DataTemplate返回类名而不是控件?

时间:2016-05-12 22:52:11

标签: c# wpf xaml datatemplate

我想创建自定义控件添加属性Info和InfoTemplate例如 我使用ContetnPresenter for Info属性在generic.xaml中定义ControlTemplate 当我不使用InfoTemplate时,它可以正常工作,但是当我应用ItemTemplate时,内容表示为类名字符串。同样的模板应用于GroupBox工作就像预期的那样。我错了什么?我在OnApplyTemplate中需要一些额外的代码?
贝娄是我的应用程序和来源的打印屏幕。红色边框是GroupBox,蓝色是我的Control。绿色边框是DataTemplate的一部分。

App print-screen

修改 为了测试我创建了MyGroupBox类,继承了GroupBox和覆盖方法OnHeaderChanged

padding

在那种情况下,GroupBox.Heder的行为类似于我的MyCustomControl并显示文本而不是控件。所以问题是:我应该在控制事件中实现什么才能像我想的那样工作?

MyCustomControl.cs

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

Generic.xaml

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));
    }
}

MainWindow.xml

<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.xaml.cs

<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>

1 个答案:

答案 0 :(得分:2)

所以废弃我的答案并重新开始我已经更好地理解了所要求的内容。这里的想法是基本上重新创建一个类似于GroupBox的自定义控件。问题是,自定义控件中的DataContext属性的Info(基本上是Header的{​​{1}}属性)不会以GroupBox的形式出现{ {1}}自定义控件本身就像使用DataContext时一样。

所以问题在于,您设置为GroupBox属性的UI块永远不会被添加为控件的逻辑子项,因此它不会以继承的方式添加在Info中使用相同代码时发生的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派生出来可能会更加清晰,因为ContentControl已经拥有所有这一切开箱即用设置,并且还有一个HeaderedContentControlHeader,您可以使用HeaderTemplateInfo属性来节省一些费用代码。

如果您希望在不打扰逻辑子等的情况下使其工作,您只需更新您设置InfoTemplate的UI块中的绑定,并让它使用搜索的Info对于自定义控件祖先,然后有一个&#34; DataContext&#34;的路径,它将手动覆盖整个问题,尽管你必须记住每次都这样做。

我敢打赌,你最好从RelativeSource派生出来,看起来应该已经找到了你想要的所有功能。