Question

I actually have two questions:

  1. How do I modify a custom control that inherits from a FrameworkElement that only holds one child (e.g. Page or ContentControl) so that it holds multiple children (like a Panel)? Can this be done from the class definition?

  2. How do I bind the children of a custom control to a Panel object (e.g WrapPanel) defined in the template of the custom control?

I'm not even sure if it is possible, but I want to create a custom control that behaves like a Page, or may even inherit from Page, but allows me to enter in children in XAML. For example, I would like the XAML for generating my custom control to look like this:

<CustomPage CustomAttribute="blah">
    <TextBox/>
    <TextBlock Text="hehe"/>
    <Label Content="ha!"/>
</CustomPage>

I want to define in the style that a WrapPanel displays the children. Something like this:

<Style TargetType="{x:Type CustomPage}">
    <Style.Setters>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CustomPage}">
                    <WrapPanel/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style.Setters>
</Style>

I would replace the WrapPanel with a ContentPresenter except that I want the ContentPresenter to behave like a WrapPanel.

I hope this is specific enough.

Était-ce utile?

La solution

You can actually do exactly what you want already with an ItemsControl.

    <ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.Items>
            <TextBox/>
            <TextBlock Text="hehe"/>
            <Label Content="ha!"/>
        </ItemsControl.Items>
    </ItemsControl>

Hope that helps

EDIT: You can use the above ItemsControl as the root element in a page to gain the page's functionality.

Autres conseils

Thank you, Murkaeus. You got me going in the right direction.

In the end, I created a custom control that inherited from Page, defining a ContentProperty for it. This apparently overrides the ContentProperty of the base class. And this works for any control type, too. Here is my code:

    [ContentProperty("Children")]
    class CustomPage : System.Windows.Controls.Page
    {
        ObservableCollection<UIElement> children = new ObservableCollection<UIElement>();
        public ObservableCollection<UIElement> Children { get { return children; } set { children = value; } }
    }

Then I defined the template for my control in the Themes/Generic.xaml file with an ItemsControl using my custom ContentProperty as a source:

    <Style TargetType="local:CustomPage">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <ItemsControl ItemsSource="{Binding Children,
                                                RelativeSource={RelativeSource TemplatedParent}}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <WrapPanel/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

I hope this helps anyone else who is looking for a solution to the same problem. And thank you again, Murkaeus, for your help!

EDIT: I should warn everyone that if you use this method, all your data bindings are lost for some reason, I discovered this with further experimentation. I ended up giving up and just specifying a panel as the child of my custom page object.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top