Wpf:如何制作自定义边框

时间:2014-10-02 16:40:39

标签: c# .net wpf

我想学习如何制作具有独特形状的自定义边框。我正在使用.Net 4.0,我已经根据路径定义了几何体。我不知道怎么做剪辑边框的子控件,调整大小等所需的所有编程...

我发现这个答案有一个博客文章的链接,解释了这是如何完成的,但解释很少,源代码下载链接被破坏了。实际上,这不是一个已回答的问题:WPF - How Can I make a custom Border

这是我到目前为止的解决方案,但边框不会像您期望的那样调整大小以适应子控件:

public class TrapezoidBorder : Border
{
    public static readonly DependencyProperty GlowBrushProperty =
        DependencyProperty.Register("GlowBrush", typeof(Brush), typeof(TrapezoidBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty CornerRadiusProperty =
        DependencyProperty.Register("CornerRadius", typeof(double), typeof(TrapezoidBorder), new FrameworkPropertyMetadata(8.0, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty OuterGlowBrushProperty =
        DependencyProperty.Register("OuterGlowBrush", typeof(Brush), typeof(TrapezoidBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty RenderIsMouseOverProperty =
        DependencyProperty.Register("RenderIsMouseOver", typeof(bool), typeof(TrapezoidBorder), new PropertyMetadata(false, new PropertyChangedCallback(OnRenderIsMouseOverChanged)));

    public static readonly DependencyProperty RenderIsPressedProperty =
        DependencyProperty.Register("RenderIsPressed", typeof(bool), typeof(TrapezoidBorder), new PropertyMetadata(false, new PropertyChangedCallback(OnRenderIsPressedChanged)));

    public static readonly DependencyProperty BorderWidthProperty =
        DependencyProperty.Register("BorderWidth", typeof(double), typeof(TrapezoidBorder), new FrameworkPropertyMetadata(2.0, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty BorderBrushProperty =
        DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(TrapezoidBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty BackgroundProperty =
        DependencyProperty.Register("Background", typeof(Brush), typeof(TrapezoidBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

    public Brush Background
    {
        get { return (Brush)GetValue(BackgroundProperty); }
        set { SetValue(BackgroundProperty, value); }
    }

    public Brush BorderBrush
    {
        get { return (Brush)GetValue(BorderBrushProperty); }
        set { SetValue(BorderBrushProperty, value); }
    }

    public double BorderWidth
    {
        get { return (double)GetValue(BorderWidthProperty); }
        set { SetValue(BorderWidthProperty, value); }
    }

    public bool RenderIsPressed
    {
        get { return (bool)GetValue(RenderIsPressedProperty); }
        set { SetValue(RenderIsPressedProperty, value); }
    }

    public bool RenderIsMouseOver
    {
        get { return (bool)GetValue(RenderIsMouseOverProperty); }
        set { SetValue(RenderIsMouseOverProperty, value); }
    }

    public Brush OuterGlowBrush
    {
        get { return (Brush)GetValue(OuterGlowBrushProperty); }
        set { SetValue(OuterGlowBrushProperty, value); }
    }

    public double CornerRadius
    {
        get { return (double)GetValue(CornerRadiusProperty); }
        set { SetValue(CornerRadiusProperty, value); }
    }

    public Brush GlowBrush
    {
        get { return (Brush)GetValue(GlowBrushProperty); }
        set { SetValue(GlowBrushProperty, value); }
    }
    protected override void OnRender(DrawingContext drawingContext)
    {
        var rc = new Rect(0, 0, this.ActualWidth, this.ActualHeight);
        var path = new Path();
        //path.Stroke = Brushes.Black;
        //path.Data =
        //    Geometry.Parse(
        //        "M130.91336,-2.6003754 L144.9668,13.820157 144.63235,155.90351 -45.593261,156.07107 -45.425622,-2.264937 z");
        Brush backBrush = GetBackgroundBrush();
        Brush borderBrush = GetBorderBrush();
        Pen borderPen = new Pen(borderBrush, BorderWidth);
        double cornerRadiusCache = CornerRadius;

        var geometry = Geometry.Parse(
            "M130.91336,-2.6003754 L144.9668,13.820157 144.63235,155.90351 -45.593261,156.07107 -45.425622,-2.264937 z");

        drawingContext.PushClip(geometry);
        drawingContext.DrawGeometry(borderBrush, borderPen, geometry);
        drawingContext.Pop();
        //base.OnRender(drawingContext);
    }

    protected override Size MeasureOverride(Size constraint)
    {
        UIElement child = this.Child as UIElement;

        double borderThickness = BorderWidth*2.0;

        if (child != null)
        {
            Size size = new Size();

            bool widthAvail = constraint.Width < borderThickness;
            bool heightAvail = constraint.Height < borderThickness;

            if (!widthAvail)
            {
                size.Width = constraint.Width - borderThickness;
            }

            if (!heightAvail)
            {
                size.Height = constraint.Height - borderThickness;
            }

            child.Measure(size);
            Size desired = child.DesiredSize;

            if (!widthAvail)
            {
                desired.Width += borderThickness;
            }
            if (!heightAvail)
            {
                desired.Height += borderThickness;
            }

            return desired;
            //return base.MeasureOverride(constraint);
        }
        return new Size(Math.Min(borderThickness, constraint.Width), Math.Min(borderThickness, constraint.Height));
    }

    protected override Size ArrangeOverride(Size arrangeSize)
    {
        return base.ArrangeOverride(arrangeSize);
    }

    private static void OnRenderIsPressedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var border = o as TrapezoidBorder;
        if (border != null)
        {
            if ((bool)e.NewValue == true)
            {
            }
            border.InvalidateVisual();
        }
    }

    // if the mouse is over the control, this fires
    private static void OnRenderIsMouseOverChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var border = o as TrapezoidBorder;
        if (border != null)
        {
            border.InvalidateVisual();
        }
    }
    protected virtual Brush GetBackgroundBrush()
    {
        Brush b = Background;
        if (b != null)
        {
            return b;
        }

        return Brushes.Orange;
    }
    protected virtual Brush GetBorderBrush()
    {
        Brush b = BorderBrush;
        if (b != null)
        {
            return b;
        }

        return Brushes.DarkGray;
    }
}

这是我尝试使用它的一些XAML:

<customControls:TrapezoidBorder 
        Grid.Column="0" 
        Grid.Row="1" 
        Grid.ColumnSpan="2" 
        Background="Blue" 
        Margin="45" 
        BorderWidth="0" BorderBrush="Crimson">
        <Grid Style="{StaticResource SubGridContainer}">
            <Grid.RowDefinitions>
                <RowDefinition Height="7*" />
                <RowDefinition Height="4*" />
                <RowDefinition Height=".5*" />
                <RowDefinition Height="88.5*" />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" VerticalAlignment="Bottom" Margin="25,0,0,10" Style="{StaticResource LargeHeader}">Customers</TextBlock>
            <StackPanel Orientation="Horizontal" Grid.Row="1" Style="{StaticResource SearchBar}">
                <TextBlock VerticalAlignment="Bottom">Search</TextBlock>
                <TextBox x:Name="SearchTerm"
                    Template="{StaticResource TextBoxBaseControlTemplate}" 
                         MinWidth="450" 
                         Margin="3"
                         cal:Message.Attach="[Event KeyDown] = [Action Search($executionContext)]"/>
                <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal">
                    <RadioButton Name="SortByLastName">Sort by Last Name</RadioButton>
                    <RadioButton Name="SortByFirstName">Soft by First Name</RadioButton>
                </StackPanel>
            </StackPanel>
            <ListBox x:Name="AccountRegistrationLogs" 
             ItemTemplate="{StaticResource AccountRegistrationLogDataTemplate}"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled"
             Background="Beige" Grid.Row="3" FontFamily="Arial" >
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="CadetBlue">
                    </SolidColorBrush>
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="LightGray">
                    </SolidColorBrush>
                </ListBox.Resources>
                <ListBox.ItemContainerStyle>
                    <StaticResource ResourceKey="AccountRegistrationLogPanelStyle"></StaticResource>
                </ListBox.ItemContainerStyle>
            </ListBox>
            <!--<TabControl Grid.Row="3" Grid.Column="0" Margin="5" TabStripPlacement="Top" 
            Style="{StaticResource TabControlStyle}" FontSize="16">
                <TabItem Header="MainTab">
                    <Border Margin="10">
                        <TextBlock Text="The quick brown fox jumps over the lazy dog."/>
                    </Border>
                </TabItem>
                <TabItem Header="VeryVeryLongTab" />
                <TabItem Header="Tab" />
            </TabControl>-->
        </Grid>
    </customControls:TrapezoidBorder>

由于

0 个答案:

没有答案