我想学习如何制作具有独特形状的自定义边框。我正在使用.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>
由于