在代码中添加元素来控制模板

时间:2017-03-01 11:23:17

标签: c# wpf controltemplate

假设我有一个共同的UserControl,它的默认值为ControlTemplate。现在我想添加一个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的派生类型。) 但是这会导致StackOverflowException崩溃:(

修改 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();
    }
}

1 个答案:

答案 0 :(得分:1)

您需要创建模板的副本。您可以使用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;