自定义控件充当允许XAML中的子项的页面

时间:2013-05-02 23:12:10

标签: wpf wpf-controls custom-controls wrappanel

我实际上有两个问题:

  1. 如何修改从仅包含一个子项(例如Page或ContentControl)的FrameworkElement继承的自定义控件,以便它包含多个子项(如Panel)?可以从类定义中完成吗?

  2. 如何将自定义控件的子项绑定到自定义控件模板中定义的Panel对象(例如WrapPanel)?

  3. 我甚至不确定它是否可行,但我想创建一个行为类似于Page的自定义控件,或者甚至可以从Page继承,但允许我在XAML中输入子项。例如,我希望生成自定义控件的XAML看起来像这样:

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

    我想在样式中定义WrapPanel显示子项。像这样:

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

    我会用ContentPresenter替换WrapPanel,除了我希望ContentPresenter的行为类似于WrapPanel。

    我希望这足够具体。

2 个答案:

答案 0 :(得分:0)

您实际上可以通过ItemsControl完成您想要的操作。

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

希望有所帮助

编辑:您可以使用上面的ItemsControl作为页面中的根元素来获取页面的功能。

答案 1 :(得分:0)

谢谢你,Murkaeus。你让我朝着正确的方向前进。

最后,我创建了一个继承自Page的自定义控件,为其定义了一个ContentProperty。这显然会覆盖基类的ContentProperty。这适用于任何控制类型。这是我的代码:

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

然后我使用我的自定义ContentProperty作为源为ItemsControl在Themes / Generic.xaml文件中为我的控件定义了模板:

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

我希望这有助于其他寻求同一问题解决方案的人。再次感谢Murkaeus,感谢您的帮助!

编辑:我应该警告大家,如果你使用这种方法,由于某些原因你的所有数据绑定都会丢失,我通过进一步的实验发现了这一点。我最终放弃了,只是将一个面板指定为我的自定义页面对象的子项。