C# 从代码隐藏更改ControlTemplate

C# 从代码隐藏更改ControlTemplate,c#,wpf,xaml,wpf-controls,controltemplate,C#,Wpf,Xaml,Wpf Controls,Controltemplate,应用程序: 您好,我正在向WPF应用程序动态添加自定义控件。该控件是一个自定义滑块。我在XAML文件中创建了一个ControlTemplate,我想用它作为这些动态创建的控件的模板。我目前正在通过以下方式应用模板: newControl.Template = (ControlTemplate)parent.Resources["nameOfTheControlTemplate"]; 目前可以正常工作(即编译、运行和应用模板) 模板如下所示:(对不起,文本墙) 我尝试过使用大量Framework

应用程序:

您好,我正在向WPF应用程序动态添加自定义控件。该控件是一个自定义滑块。我在XAML文件中创建了一个ControlTemplate,我想用它作为这些动态创建的控件的模板。我目前正在通过以下方式应用模板:

newControl.Template = (ControlTemplate)parent.Resources["nameOfTheControlTemplate"];
目前可以正常工作(即编译、运行和应用模板)

模板如下所示:(对不起,文本墙)


我尝试过使用大量FrameworkElementFactory实例创建ContentTemplate并以这种方式构建ControlTemplate,但没有成功(ControlTemplate对象非常复杂,并且有许多子元素)。

您可能不想在代码隐藏中更改模板,因为这将改变使用该模板的每个控件

相反,在呈现控件后,您可以导航控件的可视树,找到需要更改的特定元素并对其进行更改。处理完所有
Render
事件后,将运行
Loaded
事件,因此您应该能够在任何
Loaded
事件期间调整控件模板中的控件

我编写了一组我经常使用的控件,用于在WPF的可视化树中查找控件。它们可以这样使用:

Path path = VisualTreeHelpers.FindChild<Path>(newControl, "nameOfPath");
Path-Path=visualtreehelopers.FindChild(newControl,“路径名称”);
我强烈反对在运行时篡改模板(或者更确切地说是从模板实例化的控件),因为这样做是不好的设计

您想要做的是使用属性。例如,将
路径.Fill
绑定到
前台
?如果您认为这在语义上不够合适,那么最好继承
Slider
并创建所需的属性,而不是在运行时处理模板

在您的情况下,您有嵌套的模板,因此您必须转发
TemplateBinding
或使用
RelativeSource
绑定来做一些事情,这取决于您自己。e、 g.使用转发:

<!-- ... -->
<Thumb x:Name="Thumb" HorizontalContentAlignment="Right" Width="7"
            Background="{TemplateBinding Foreground}">
        <Thumb.Template>
            <ControlTemplate TargetType="Thumb">
                <Path x:Name="nameOfPath" Stroke="Black" StrokeThickness="0"
                      Fill="{TemplateBinding Background}">

这将
Path.Fill
绑定到
Thumb.Background
(实际情况)上,
Thumb.Background
绑定到
滑块.Foreground
,这似乎也很合理。现在您只需在
滑块上设置
前景
,即可设置路径的
填充
,很好,不是吗


旁白:你应该把你想要的东西抽象化

我想稍微修改一下这个控制模板


事实上,这不是你想要的,而是你认为得到你想要的东西所需要的结果。你把你真正想要的放在括号里:“[更改]路径对象的填充颜色”

+1正是因为有这样一个布局良好的问题您好,我尝试了你的建议,但没有成功。当我调用
VisualTreeHelper.GetChildrenCount(父级)时它返回0。我甚至尝试过用ControlTemplate传递一个非动态创建的控件对象,但它仍然返回一个0的子计数。@user989056您的控件呈现了吗?如果您在代码隐藏中创建了控件,则可能需要向其附加一个进行更改的
Loaded
事件,然后将该控件添加到UI中,以便它可以呈现。渲染完成后,加载的事件将触发,VisualTreeHelper将能够找到它的子级。谢谢。您的解决方案“感觉”更干净。哦,真的更干净:)
Path path = VisualTreeHelpers.FindChild<Path>(newControl, "nameOfPath");
<!-- ... -->
<Thumb x:Name="Thumb" HorizontalContentAlignment="Right" Width="7"
            Background="{TemplateBinding Foreground}">
        <Thumb.Template>
            <ControlTemplate TargetType="Thumb">
                <Path x:Name="nameOfPath" Stroke="Black" StrokeThickness="0"
                      Fill="{TemplateBinding Background}">