在代码中添加元素到控件模板

Add element to control template in code

假设我有一个默认为 ControlTemplate 的公共 UserControl。现在我想添加一个 AdornerDecorator 作为 ControlTemplate.

的根元素

我该怎么做?

到目前为止我的尝试如下:

UserControl view;
var templateWithAdornerDecorator = new ControlTemplate(view.GetType());
var adornerDecorator = new FrameworkElementFactory(typeof(AdornerDecorator));
var otherView = new FrameworkElementFactory(view.GetType());
otherView.SetValue(Control.TemplateProperty, view.Template);
adornerDecorator.AppendChild(otherView);
templateWithAdornerDecorator.VisualTree = adornerDecorator;
view.Template = templateWithAdornerDecorator;

(我的 view 可能是 UserControl 的派生类型。) 但这会因 WhosebugException 崩溃:(

编辑: MyUserControl 有这个 xaml:

<UserControl x:Class="MyNameSpace.Wpf.Sample.MyUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    ABA
</UserControl>

这是 xaml.cs:

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
    }
}

您需要创建模板的副本。您可以使用 XamlWriter/XamlReader 类 克隆现有模板。

试试这个:

MyUserControl view = new MyUserControl();
string xaml;
ControlTemplate ct = view.Template;
using (var stream = new System.IO.MemoryStream())
{
    System.Windows.Markup.XamlWriter.Save(ct, stream);
    xaml = Encoding.ASCII.GetString(stream.ToArray());
}

XNamespace ns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
XDocument oldTemplateXml = XDocument.Parse(xaml);
XElement newTemplateXml = new XElement(ns + "ControlTemplate",
new XElement(ns + "AdornerDecorator", oldTemplateXml.Root.DescendantNodes().First()));

ControlTemplate newTemplate = System.Windows.Markup.XamlReader.Parse(newTemplateXml.ToString()) as ControlTemplate;
view.Template = newTemplate;