我在 XAML 中有这个
<ControlTemplate TargetType="{x:Type Button}">
<Image ...>
</ControlTemplate>
我想在 C# 代码中实现相同的目标。我怎样才能做到这一点?
ControlTemplate ct = new ControlTemplate();..
Image img = new Image();..
现在如何将此图像分配给控制模板?我们可以这样做还是我在这里遗漏了任何概念?
我在 XAML 中有这个
<ControlTemplate TargetType="{x:Type Button}">
<Image ...>
</ControlTemplate>
我想在 C# 代码中实现相同的目标。我怎样才能做到这一点?
ControlTemplate ct = new ControlTemplate();..
Image img = new Image();..
现在如何将此图像分配给控制模板?我们可以这样做还是我在这里遗漏了任何概念?
在代码隐藏中创建模板不是一个好主意,理论上可以通过定义ControlTemplate.VisualTree
which is a来做到这一点FrameworkElementFactory
。
ControlTemplate template = new ControlTemplate(typeof(Button));
var image = new FrameworkElementFactory(typeof(Image));
template.VisualTree = image;
分配属性非常迂回,因为您需要使用SetValue
and SetBinding
:
image.SetValue(Image.SourceProperty, ...);
此外,关于(以前)接受的答案和引用的内容:
以编程方式设置 ControlTemplate 就像使用 XAML 一样,因为我们必须使用 XamlReader 类。
这种说法是错误的,我们没有“必须”。
如果我在运行时分配模板,我将它们定义为我可以在需要时加载的资源。
编辑:根据文档FrameworkElementFactory
已弃用:
此类是一种以编程方式创建模板的弃用方式,模板是 FrameworkTemplate 的子类,例如 ControlTemplate 或 DataTemplate;使用此类创建模板时,并非所有模板功能都可用。以编程方式创建模板的推荐方法是使用 XamlReader 类的 Load 方法从字符串或内存流加载 XAML。
我想知道这个建议是否是个好主意。如果我可以避免使用字符串和XamlReader
.
以编程方式设置 ControlTemplate 就像使用 XAML 一样,因为我们必须使用 XamlReader 类。例如,这里是设置按钮模板的代码,假设我们要在加载后设置按钮的模板。
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);
}
由于我们使用字符串来指定模板的 XAML 代码,因此我们可以使用 XamlReader 的 Parse 方法。XamlReader 还有一个 Load 方法,主要用于流或 XAML 或 XML 阅读器。请注意,我们必须包含 XML 命名空间 http://schemas.microsoft.com/winfx/2006/xaml/presentation ,因为我们需要的 ControlTemplate、Border 和其他控件都在那里定义。如果我们没有包含它,我们将遇到运行时异常。基本上,我们必须放置模板所需的命名空间。
如果您只需要更改按钮图像,那么您可以做一件事。
现在在 XAML 中在按钮模板中使用它
在 CurrentButtonImage 的属性更改上使用更新按钮的图像(在后面的代码中)
CurrentImagePropertyChangedhandler(....,...)
{
switch(CurrentButtonImage)
{
case "Image1" :
this._ButtonImage.Fill = (DrawingBrush)csd.FindResource("Image1DrawingBrush");
break;
}
}