如何在C#/ WPF中为网格添加边框?
这就是我想要的,但是在整个事物中放置一个边框而不是我在我的应用程序中放置的网格控件。
<Grid>
<Border BorderBrush="Black" BorderThickness="2">
<Grid Height="166" HorizontalAlignment="Left" Margin="12,12,0,0" Name="grid1" VerticalAlignment="Top" Width="479" Background="#FFF2F2F2" />
</Border>
... and so on ...
答案 0 :(得分:189)
如果您只想要一个外边框,最简单的方法是将它放在边框控件中:
<Border BorderBrush="Black" BorderThickness="2">
<Grid>
<!-- Grid contents here -->
</Grid>
</Border>
您看到边框完全填满您的控件的原因是,默认情况下,它的HorizontalAlignment和VerticalAlignment设置为Stretch。请尝试以下方法:
<Grid>
<Border HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="2">
<Grid Height="166" HorizontalAlignment="Left" Margin="12,12,0,0" Name="grid1" VerticalAlignment="Top" Width="479" Background="#FFF2F2F2" />
</Border>
</Grid>
这应该可以让你得到你所追求的东西(尽管你可能希望在所有4个方面都留有余量,而不只是2 ...)
答案 1 :(得分:7)
如果将网格嵌套在边框控件中
<Border>
<Grid>
</Grid>
</Border>
没有做你想做的事情,那么你将不得不为你想要的网格(或边框)制作自己的控制模板。
答案 2 :(得分:1)
我认为您的问题是边距应该在边框标记中指定,而不是在网格中指定。
答案 3 :(得分:1)
<Grid x:Name="outerGrid">
<Grid x:Name="innerGrid">
<Border BorderBrush="#FF179AC8" BorderThickness="2" />
<other stuff></other stuff>
<other stuff></other stuff>
</Grid>
</Grid>
此代码在&#34; innerGrid&#34;
中包装边框答案 4 :(得分:1)
这是一个后来的答案对我有用,如果它可能对将来的任何人都有用。我希望在网格的四个边上都有一个简单的边框,我就这样实现了......
<DataGrid x:Name="dgDisplay" Margin="5" BorderBrush="#1266a7" BorderThickness="1"...
答案 5 :(得分:0)
如果有人对类似问题感兴趣,但不使用XAML,这是我的解决方案:
var B1 = new Border();
B1.BorderBrush = Brushes.Black;
B1.BorderThickness = new Thickness(0, 1, 0, 0); //You can specify here which borders do you want
YourPanel.Children.Add(B1);
答案 6 :(得分:0)
这是我的解决方案,希望对你有用:
public class Sheet : Grid
{
public static readonly DependencyProperty BorderBrushProperty = DependencyProperty.Register(nameof(BorderBrush), typeof(Brush), typeof(Sheet), new FrameworkPropertyMetadata(Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnBorderBrushChanged));
public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register(nameof(BorderThickness), typeof(double), typeof(Sheet), new FrameworkPropertyMetadata(1D, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnBorderThicknessChanged, CoerceBorderThickness));
public static readonly DependencyProperty CellSpacingProperty = DependencyProperty.Register(nameof(CellSpacing), typeof(double), typeof(Sheet), new FrameworkPropertyMetadata(0D, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnCellSpacingChanged, CoerceCellSpacing));
public Brush BorderBrush
{
get => this.GetValue(BorderBrushProperty) as Brush;
set => this.SetValue(BorderBrushProperty, value);
}
public double BorderThickness
{
get => (double)this.GetValue(BorderThicknessProperty);
set => this.SetValue(BorderThicknessProperty, value);
}
public double CellSpacing
{
get => (double)this.GetValue(CellSpacingProperty);
set => this.SetValue(CellSpacingProperty, value);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
Size size = base.ArrangeOverride(arrangeSize);
double border = this.BorderThickness;
double doubleBorder = border * 2D;
double spacing = this.CellSpacing;
double halfSpacing = spacing * 0.5D;
if (border > 0D || spacing > 0D)
{
foreach (UIElement child in this.InternalChildren)
{
this.GetChildBounds(child, out double left, out double top, out double width, out double height);
left += halfSpacing + border;
top += halfSpacing + border;
height -= spacing + doubleBorder;
width -= spacing + doubleBorder;
if (width < 0D)
{
width = 0D;
}
if (height < 0D)
{
height = 0D;
}
left -= left % 0.5D;
top -= top % 0.5D;
width -= width % 0.5D;
height -= height % 0.5D;
child.Arrange(new Rect(left, top, width, height));
}
if (border > 0D && this.BorderBrush != null)
{
this.InvalidateVisual();
}
}
return size;
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (this.BorderThickness > 0D && this.BorderBrush != null)
{
if (this.CellSpacing == 0D)
{
this.DrawCollapsedBorder(dc);
}
else
{
this.DrawSeperatedBorder(dc);
}
}
}
private void DrawSeperatedBorder(DrawingContext dc)
{
double spacing = this.CellSpacing;
double halfSpacing = spacing * 0.5D;
#region draw border
Pen pen = new Pen(this.BorderBrush, this.BorderThickness);
UIElementCollection children = this.InternalChildren;
foreach (UIElement child in children)
{
this.GetChildBounds(child, out double left, out double top, out double width, out double height);
left += halfSpacing;
top += halfSpacing;
width -= spacing;
height -= spacing;
dc.DrawRectangle(null, pen, new Rect(left, top, width, height));
}
#endregion
}
private void DrawCollapsedBorder(DrawingContext dc)
{
RowDefinitionCollection rows = this.RowDefinitions;
ColumnDefinitionCollection columns = this.ColumnDefinitions;
int rowCount = rows.Count;
int columnCount = columns.Count;
const byte BORDER_LEFT = 0x08;
const byte BORDER_TOP = 0x04;
const byte BORDER_RIGHT = 0x02;
const byte BORDER_BOTTOM = 0x01;
byte[,] borderState = new byte[rowCount, columnCount];
int column = columnCount - 1;
int columnSpan;
int row = rowCount - 1;
int rowSpan;
#region generate main border data
for (int i = 0; i < rowCount; i++)
{
borderState[i, 0] = BORDER_LEFT;
borderState[i, column] = BORDER_RIGHT;
}
for (int i = 0; i < columnCount; i++)
{
borderState[0, i] |= BORDER_TOP;
borderState[row, i] |= BORDER_BOTTOM;
}
#endregion
#region generate child border data
UIElementCollection children = this.InternalChildren;
foreach (UIElement child in children)
{
this.GetChildLayout(child, out row, out rowSpan, out column, out columnSpan);
for (int i = 0; i < rowSpan; i++)
{
borderState[row + i, column] |= BORDER_LEFT;
borderState[row + i, column + columnSpan - 1] |= BORDER_RIGHT;
}
for (int i = 0; i < columnSpan; i++)
{
borderState[row, column + i] |= BORDER_TOP;
borderState[row + rowSpan - 1, column + i] |= BORDER_BOTTOM;
}
}
#endregion
#region draw border
Pen pen = new Pen(this.BorderBrush, this.BorderThickness);
double left;
double top;
double width, height;
for (int r = 0; r < rowCount; r++)
{
RowDefinition v = rows[r];
top = v.Offset;
height = v.ActualHeight;
for (int c = 0; c < columnCount; c++)
{
byte state = borderState[r, c];
ColumnDefinition h = columns[c];
left = h.Offset;
width = h.ActualWidth;
if ((state & BORDER_LEFT) == BORDER_LEFT)
{
dc.DrawLine(pen, new Point(left, top), new Point(left, top + height));
}
if ((state & BORDER_TOP) == BORDER_TOP)
{
dc.DrawLine(pen, new Point(left, top), new Point(left + width, top));
}
if ((state & BORDER_RIGHT) == BORDER_RIGHT && (c + 1 >= columnCount || (borderState[r, c + 1] & BORDER_LEFT) == 0))
{
dc.DrawLine(pen, new Point(left + width, top), new Point(left + width, top + height));
}
if ((state & BORDER_BOTTOM) == BORDER_BOTTOM && (r + 1 >= rowCount || (borderState[r + 1, c] & BORDER_TOP) == 0))
{
dc.DrawLine(pen, new Point(left, top + height), new Point(left + width, top + height));
}
}
}
#endregion
}
private void GetChildBounds(UIElement child, out double left, out double top, out double width, out double height)
{
ColumnDefinitionCollection columns = this.ColumnDefinitions;
RowDefinitionCollection rows = this.RowDefinitions;
int rowCount = rows.Count;
int row = (int)child.GetValue(Grid.RowProperty);
if (row >= rowCount)
{
row = rowCount - 1;
}
int rowSpan = (int)child.GetValue(Grid.RowSpanProperty);
if (row + rowSpan > rowCount)
{
rowSpan = rowCount - row;
}
int columnCount = columns.Count;
int column = (int)child.GetValue(Grid.ColumnProperty);
if (column >= columnCount)
{
column = columnCount - 1;
}
int columnSpan = (int)child.GetValue(Grid.ColumnSpanProperty);
if (column + columnSpan > columnCount)
{
columnSpan = columnCount - column;
}
left = columns[column].Offset;
top = rows[row].Offset;
ColumnDefinition right = columns[column + columnSpan - 1];
width = right.Offset + right.ActualWidth - left;
RowDefinition bottom = rows[row + rowSpan - 1];
height = bottom.Offset + bottom.ActualHeight - top;
if (width < 0D)
{
width = 0D;
}
if (height < 0D)
{
height = 0D;
}
}
private void GetChildLayout(UIElement child, out int row, out int rowSpan, out int column, out int columnSpan)
{
int rowCount = this.RowDefinitions.Count;
row = (int)child.GetValue(Grid.RowProperty);
if (row >= rowCount)
{
row = rowCount - 1;
}
rowSpan = (int)child.GetValue(Grid.RowSpanProperty);
if (row + rowSpan > rowCount)
{
rowSpan = rowCount - row;
}
int columnCount = this.ColumnDefinitions.Count;
column = (int)child.GetValue(Grid.ColumnProperty);
if (column >= columnCount)
{
column = columnCount - 1;
}
columnSpan = (int)child.GetValue(Grid.ColumnSpanProperty);
if (column + columnSpan > columnCount)
{
columnSpan = columnCount - column;
}
}
private static void OnBorderBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
if (d is UIElement element)
{
element.InvalidateVisual();
}
}
private static void OnBorderThicknessChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
if (d is UIElement element)
{
element.InvalidateArrange();
}
}
private static void OnCellSpacingChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
if (d is UIElement element)
{
element.InvalidateArrange();
}
}
private static object CoerceBorderThickness(DependencyObject d, object baseValue)
{
if (baseValue is double value)
{
return value < 0D || double.IsNaN(value) || double.IsInfinity(value) ? 0D : value;
}
return 0D;
}
private static object CoerceCellSpacing(DependencyObject d, object baseValue)
{
if (baseValue is double value)
{
return value < 0D || double.IsNaN(value) || double.IsInfinity(value) ? 0D : value;
}
return 0D;
}
}