1

我对 wpf 很陌生。

我正在尝试制作一个带有一些精美设计边框的自定义面板。我让一切正常,但前提是我在自定义面板中只有 1 个控件。如果我尝试添加多个,则会出现以下异常:

对象“BordersPanel”已经有一个孩子,不能添加“按钮”。'BordersPanel' 只能接受一个孩子。

我花了很多时间试图在网上找到解决方案,但到目前为止还没有。所以我正在向社区寻求帮助。

面板样式:

    <Style
    TargetType="{x:Type local:BordersPanel}">
    <Setter
        Property="Template">
        <Setter.Value>
            <ControlTemplate
                TargetType="{x:Type local:BordersPanel}">
                <Grid Margin="0,0,0,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="10.8" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="10.8" />
                    </Grid.RowDefinitions>
                    <local:Border
                        x:Name="topBorder"
                        Grid.Row="0"
                        Margin="0"
                        HorizontalAlignment="Stretch"
                        VerticalAlignment="top"
                        BlocksSize="{TemplateBinding BlocksSize}"
                        Width="Auto"
                        Height="10.8"/>

                    <ScrollViewer
                        Grid.Row="1"
                        HorizontalScrollBarVisibility="Auto"
                        VerticalScrollBarVisibility="Auto">
                        <ContentPresenter
                            Cursor="{TemplateBinding Cursor}"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                            Margin="{TemplateBinding Padding}"
                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                            Content="{TemplateBinding Content}"
                            ContentTemplate="{TemplateBinding ContentTemplate}"/>
                    </ScrollViewer>
                    <local:Border
                        x:Name="bottomBorder"
                        Grid.Row="2"
                        Margin="0"
                        VerticalAlignment="Bottom"
                        HorizontalAlignment="Stretch"
                        BlocksSize="{TemplateBinding BottomBlocksSize}"
                        Width="Auto"
                        Height="10.8"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

后面的 C# 代码:

    class BordersPanel : ContentControl
{
    public static readonly DependencyProperty BlocksSizeProperty =
        DependencyProperty.Register("BlocksSize", typeof(string), typeof(BordersPanel));

    public static readonly DependencyProperty BottomBlocksSizeProperty =
        DependencyProperty.Register("BottomBlocksSize", typeof(string), typeof(BordersPanel));

    private Border topBorder;

    private Border bottomBorder;

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);

        if (e.Property == BordersPanel.BlocksSizeProperty)
        {
            BottomBlocksSize = BlocksSize + ";T";
        }
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        topBorder = GetTemplateChild("topBorder") as Border;
        bottomBorder = GetTemplateChild("bottomBorder") as Border;
    }

    static BordersPanel()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(BordersPanel),
            new FrameworkPropertyMetadata(typeof(BordersPanel)));
    }

    public BordersPanel()
    {
        SizeChanged += new SizeChangedEventHandler(Border_SizeChanged);
    }

    public string BlocksSize
    {
        get
        {
            return (string)GetValue(BlocksSizeProperty);
        }
        set
        {
            SetValue(BlocksSizeProperty, value);
        }
    }

    protected string BottomBlocksSize
    {
        get
        {
            return (string)GetValue(BottomBlocksSizeProperty);
        }
        set
        {
            SetValue(BottomBlocksSizeProperty, value);
        }
    }

    private void Border_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        double available = Width;
        if (Double.IsNaN(available) == true)
        {
            available = ActualWidth;
        }

        if (topBorder != null)
        {
            topBorder.Width = available;
        }
        if (bottomBorder != null)
        {
            bottomBorder.Width = available;
        }
    }
}

这就是我使用它的方式:

    <local:BordersPanel
        BlocksSize="LL50;ML50;RU"
        Height="208" Canvas.Left="213" Canvas.Top="56.82" Width="428.5">
        <local:BinarySquares Margin="0,0,10,15" HorizontalAlignment="Right" VerticalAlignment="Bottom" d:LayoutOverrides="Width, Height"/>
        <Button Content="Button" HorizontalAlignment="Stretch" Height="300"/>
    </local:BordersPanel>

我很确定我遗漏了一些非常明显的东西,但这就是明显的东西,你越看它们,它们就越能躲避你......

顺便说一句,如果您认为有更好的方法来做我所做的事情(使用绑定、面板等),欢迎发表评论。:)

要非常清楚:在我使用之前:

    <local:Border
        Margin="0"
        VerticalAlignment="top"
        BlocksSize="LL50;ML200;RU"
        Width="Auto" Height="10.8" HorizontalAlignment="Stretch" d:LayoutOverrides="Width"/>
    <local:BinarySquares Margin="0,0,10,15" HorizontalAlignment="Right" VerticalAlignment="Bottom" d:LayoutOverrides="Width, Height"/>
    <Grid  Margin="8,14.8,8,24">
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
            <Canvas x:Name="pnl_Content5" Margin="0,0,0,0">
                <Button Content="Button" HorizontalAlignment="Stretch" Canvas.Left="77" Canvas.Top="44"/>
            </Canvas>
        </ScrollViewer>
    </Grid>
    <local:Border
        Margin="0"
        VerticalAlignment="Bottom"
        BlocksSize="LL50;ML200;RU;T"
        Width="Auto" Height="10.8" HorizontalAlignment="Stretch"/>

每次使用面板时,我都会一遍又一遍地使用此代码。

显然我在前面的代码块中写的更短,更容易维护。(至少在我看来)这就是为什么我制作这个带有边框的自定义面板以避免重复代码。

4

1 回答 1

1

好吧,我找到了一个可行的解决方案。这不完全是我想要的,但它足够接近它会做。我只是在 BordersPanel 实例中放置了一个网格声明。我宁愿不必这样做,但我猜这样它实际上允许我在面板内使用任何类型的布局。

            <local:BordersPanel
                BlocksSize="LL50;ML50;RU"
                Margin="0">
                <Grid>
                    <local:BinarySquares Margin="0,0,10,15" HorizontalAlignment="Right" VerticalAlignment="Bottom" d:LayoutOverrides="Width, Height"/>
                    <Button Content="Button" HorizontalAlignment="Stretch" Height="300"/>
                </Grid>
            </local:BordersPanel>
于 2013-08-01T12:58:51.940 回答