简体   繁体   中英

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

I currently have a class that inherits from Control and I give it a custom shape by setting its style to a style defined in the xaml resources:

<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>

I was able to define all sorts of mouse events on this control and get it to behave as I want. Now, I want to dynamically add nested controls inside this control, and I want each one of those nested controls to have custom shapes, and mouse events etc, all defined at runtime. Almost none of the UI is static so its all defined at runtime. I tried adding controls, buttons as visual children, logical children, and nothing shows up in the UI. I don't even see anything in the live visual tree. What am I doing wrong here ? Should I be taking a different approach ? How can I access the Style > Setter.Value > ControlTemplate > Canvas at runtime to add more content to it ? Also, the content is different for each instance of the control.

I saw this post which asks a very similar question but the answer is a verbal description and I don't know how to implement this. I also found many solutions that write static UI in xaml but when I try to recreate that in C# it just doesn't work. I couldn't find any other examples on how to do this. Any help is appreciated, thanks!

You'll save yourself a lot of headache in future if you do things properly and use data-binding instead of manipulating the GUI elements directly, but if you insist...

You need to use the Visual Tree Helper to traverse the control in order to find the templated framework element. You may also may need to call ApplyTemplate first to make sure that your control has been templated and is ready to access:

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);

In this code I've just assumed that the first element in the template would be a Canvas, in practice you might prefer to search the visual tree for your canvas element (see here and here for more info).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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