动态创建的形状面板,内部有嵌套控件(也是动态创建的),也有自定义形状

Dynamically created shaped panel with nested controls (also dynamically created) inside, which also have custom shapes

我目前有一个继承自 Control 的 class,我通过将其样式设置为 xaml 资源中定义的样式来为其自定义形状:

<Style x:Key="ParameterStyle" TargetType="{x:Type local:ParameterUI}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ParameterUI}">
                <Canvas>
                    <Ellipse 
                    x:Name="component" 
                    HorizontalAlignment="Left" Height="50" 
                    Margin="0,0,0,50" Stroke="#FF8E8E9F" 
                    VerticalAlignment="Top" Width="50" 
                    StrokeThickness="1.5" Fill="#FF202020"/>
                </Canvas>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我能够在此控件上定义各种鼠标事件,并使其按照我的意愿运行。现在,我想在此控件中动态添加嵌套控件,并且我希望这些嵌套控件中的每一个都具有自定义形状和鼠标事件等,所有这些都是在运行时定义的。 UI 的几乎 none 是静态的,所以它都是在运行时定义的。我尝试添加控件、按钮作为视觉子项、逻辑子项,但 UI 中没有显示任何内容。我什至在实时可视化树中看不到任何东西。我在这里做错了什么?我应该采取不同的方法吗?如何在运行时访问 Style > Setter.Value > ControlTemplate > Canvas 以向其中添加更多内容?此外,控件的每个实例的内容都不同。

我看到 this post 问了一个非常相似的问题,但答案是口头描述,我不知道如何实现。我还发现许多在 xaml 中写入静态 UI 的解决方案,但是当我尝试在 C# 中重新创建它时,它就不起作用了。我找不到关于如何执行此操作的任何其他示例。感谢任何帮助,谢谢!

如果你正确地做事并使用数据绑定而不是直接操作 GUI 元素,你将来会省去很多麻烦,但如果你坚持...

您需要使用 Visual Tree Helper 遍历控件才能找到模板化框架元素。您可能还需要先调用 ApplyTemplate 以确保您的控件已模板化并准备好访问:

yourTemplatedControl.ApplyTemplate();
var canvas = VisualTreeHelper.GetChild(yourTemplatedControl, 0) as Canvas;

var ellipse = new Ellipse();
ellipse.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
ellipse.VerticalAlignment = System.Windows.VerticalAlignment.Top;
ellipse.Width = 50;
ellipse.Height = 50;
ellipse.Margin = new Thickness(0, 0, 0, 50);
ellipse.Stroke = Brushes.Blue;
ellipse.StrokeThickness = 1.5;
ellipse.Fill = Brushes.Yellow;
canvas.Children.Add(ellipse);

在此代码中,我假设模板中的第一个元素是 Canvas,实际上您可能更愿意在可视化树中搜索 canvas 元素(请参阅 here and here了解更多信息)。