简体   繁体   English

如何在代码中设置控制模板?

[英]How to set Control Template in code?

I have this in XAML 我在XAML中有这个

<ControlTemplate TargetType="{x:Type Button}">
    <Image ...>
</ControlTemplate>

I want to achieve same in C# code. 我希望在C#代码中实现相同的功能。 How can I achieve this? 我怎样才能做到这一点?

ControlTemplate ct = new ControlTemplate();..
Image img = new Image();..

Now how to assign this Image to Control template? 现在如何将此图像分配给控制模板? Can we do this or Am I missing any concept here? 我们能做到这一点还是我错过了这里的概念?

Creating template in codebehind is not a good idea, in theory one would do this by defining the ControlTemplate.VisualTree which is a FrameworkElementFactory . 在代码隐藏中创建模板不是一个好主意,理论上可以通过定义ControlTemplate.VisualTreeFrameworkElementFactory

ControlTemplate template = new ControlTemplate(typeof(Button));
var image = new FrameworkElementFactory(typeof(Image));
template.VisualTree = image;

Assigning properties is very roundabout since you need to use SetValue and SetBinding : 由于您需要使用SetValueSetBinding分配属性非常迂回:

image.SetValue(Image.SourceProperty, ...);

Also, about the (previously) accepted answer and the stuff quoted: 此外,关于(以前)接受的答案和引用的东西:

Setting the ControlTemplate programmatically is just like using XAML because we have to use the XamlReader class. 以编程方式设置ControlTemplate就像使用XAML一样,因为我们必须使用XamlReader类。

That statement is just wrong, we do not "have to" . 那句话是错的,我们不“必须”


If i assign templates at run time i define them as a resource which i can load if i need it. 如果我在运行时分配模板,我将它们定义为一个资源,如果我需要它我可以加载。


Edit: According to the documentation FrameworkElementFactory is deprecated: 编辑:根据文档FrameworkElementFactory不推荐使用:

This class is a deprecated way to programmatically create templates, which are subclasses of FrameworkTemplate such as ControlTemplate or DataTemplate; 此类是以编程方式创建模板的不推荐使用的方式,模板是FrameworkTemplate的子类,如ControlTemplate或DataTemplate; not all of the template functionality is available when you create a template using this class. 使用此类创建模板时,并非所有模板功能都可用。 The recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class. 以编程方式创建模板的推荐方法是使用XamlReader类的Load方法从字符串或内存流加载XAML。

I wonder if this recommendation is such a good idea. 我想知道这个建议是不是一个好主意。 Personally i would still go with defining the template as a resource in XAML if i can avoid doing it with strings and the XamlReader . 我个人仍然会将模板定义为XAML中的资源,如果我可以避免使用字符串和XamlReader

http://www.eggheadcafe.com/sample-code/SilverlightWPFandXAML/73fdb6a2-6044-4c43-8766-afa12618ddc1/set-controltemplate-programmatically.aspx http://www.eggheadcafe.com/sample-code/SilverlightWPFandXAML/73fdb6a2-6044-4c43-8766-afa12618ddc1/set-controltemplate-programmatically.aspx

Setting the ControlTemplate programmatically is just like using XAML because we have to use the XamlReader class. 以编程方式设置ControlTemplate就像使用XAML一样,因为我们必须使用XamlReader类。 For example, here is the code to set a button's template, assuming that we want to set a button's template after it is loaded. 例如,这里是设置按钮模板的代码,假设我们想要在加载后设置按钮的模板。

private void Button_Loaded(object sender, RoutedEventArgs e) {
    var button = sender as Button;
    string template =
        "<ControlTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
            TargetType=\"Button\">" +
            "<Border>" +
                 "<ContentPresenter/>" +
            "</Border>" +
        "</ControlTemplate>";
    button.Template = (ControlTemplate)XamlReader.Parse(template);
}

Since we used a string for specifying the XAML code for the template, we can use the XamlReader's Parse method. 由于我们使用字符串来指定模板的XAML代码,因此我们可以使用XamlReader的Parse方法。 The XamlReader also has a Load method, which is primarily used for streams or XAML or XML readers. XamlReader还有一个Load方法,主要用于流或XAML或XML读取器。 Notice that we have to include the XML namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation because the ControlTemplate, Border, and other controls we need are defined there. 请注意,我们必须包含XML命名空间http://schemas.microsoft.com/winfx/2006/xaml/presentation,因为我们需要在那里定义ControlTemplate,Border和其他控件。 If we did not include it, we'll encounter a runtime exception. 如果我们不包含它,我们将遇到运行时异常。 Basically, we have to put the namespaces needed by the template. 基本上,我们必须放置模板所需的名称空间。

If you need to change the button image only then you can do one thing. 如果您只需要更改按钮图像,那么您可以做一件事。

  1. Create a dependency property which will represent when you want to change the image (a bool) or may be you can create an enum which has all possible images say 创建一个依赖项属性,它将表示您想要更改图像的时间(bool),或者您可以创建一个包含所有可能图像的枚举
  2. Enum Images { Image1 = 0, Image2 = 1, Image2 = 3}. 枚举图像{Image1 = 0,Image2 = 1,Image2 = 3}。 Create a dependency property "CurrentButtonImage" of this type which will be associated with button. 创建此类型的依赖项属性“CurrentButtonImage”,该属性将与button关联。

Now in XAML use this in button template 现在在XAML中使用此按钮模板

On property Change of CurrentButtonImage update the image of button (in code behind) using 在属性Change of CurrentButtonImage更新按钮的图像(在代码后面)使用

CurrentImagePropertyChangedhandler(....,...)  
{  
    switch(CurrentButtonImage)  
    {  
        case "Image1" :  
          this._ButtonImage.Fill = (DrawingBrush)csd.FindResource("Image1DrawingBrush");
          break;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM