我想创建自定义控件添加属性Info和InfoTemplate .
我使用ContetnPresenter for Info属性在generic.xaml中定义ControlTemplate .
当我没有't use InfoTemplate it' s工作正常,但当我应用ItemTemplate时,内容表示为类名字符串 . 同样的模板应用于GroupBox工作就像预期的那样 . 我错了什么?我在OnApplyTemplate中需要一些额外的代码?
贝娄是我的应用程序和来源的打印屏幕 . 红色边框是GroupBox,蓝色是我的Control . 绿色边框是DataTemplate的一部分 .
EDIT: 为了测试我创建了MyGroupBox类,继承了GroupBox的形式并重写方法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();
}
}
}
1 回答
所以废弃我的答案并重新开始,我对所要求的内容有了更好的理解 . 这里的想法是基本上重新创建一个自定义
GroupBox
类似的控件 . 问题是自定义控件中Info
属性的DataContext
(基本上是GroupBox
的Header
属性)不是自定义控件本身的DataContext
,就像使用GroupBox
时那样 .所以问题是你设置为
Info
属性的UI块永远不会被添加为控件的逻辑子代,因此它不会以这样的方式添加,即继承DataContext
,正如相同代码所发生的那样 . 用于GroupBox
. 为此,只需将自定义控件类更新为以下内容:这将解决问题,但是,应该说,从
HeaderedContentControl
而不是从ContentControl
派生出来可能会更清晰,因为HeaderedContentControl
已经为您开箱即用,并且已经有Header
和HeaderTemplate
,您可以使用Info
和InfoTemplate
属性来保存一些代码 .如果你想在不打扰逻辑子等的情况下使用它,你可以只更新你设置
Info
的UI块中的绑定,让它使用RelativeSource
搜索自定义控件祖先,然后有一个路径"DataContext",这将手动覆盖整个问题,但您必须记住每次都这样做 .我敢打赌,你最好从
HeaderedContentControl
派生,它看起来应该具有你想要的所有功能 .