gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 16:49:07 25 4
gpt4 key购买 nike

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

App print-screen

编辑:为了进行测试,我创建了继承自 GroupBox 的类 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>

主窗口.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();
}
}
}

最佳答案

所以放弃我的回答并重新开始,因为我对所要求的内容有了更好的理解。这里的想法基本上是重新创建自定义 GroupBox 之类的控件。问题是自定义控件中 Info 属性的 DataContext(基本上是 GroupBoxHeader 属性>) 不像使用 GroupBox 时那样作为自定义控件本身的 DataContext 出现。

所以问题在于,您设置为 Info 属性的 UI block 永远不会添加为控件的逻辑子控件,因此它不会以继承的方式添加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 派生为 HeaderedContentControl 可能会更清晰 已经为您设置了所有这些开箱即用的设置,并且已经有一个 HeaderHeaderTemplate 可以用来代替您的 InfoInfoTemplate 属性可以为您节省一些代码。

如果你想在不打扰逻辑子等的情况下让它工作,你可以只更新你设置 Info 的 UI block 中的绑定(bind),并让它使用 RelativeSource 搜索自定义控件祖先,然后有一个“DataContext”路径,这将手动覆盖整个问题,尽管您必须记住每次都这样做。

我敢打赌,您最好只从 HeaderedContentControl 派生,它看起来应该已经内置了您正在寻找的所有功能。

关于c# - 为什么 DataTemplate 返回类名而不是控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37198721/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com