你应该能够使用附加属性来完成此操作,而无需创建自定义或用户控件。
这是一个我认为可以实现你想要的功能的类。不要将Grid.Row
和Grid.RowSpan
的值绑定到行和高度上,而是将GridEx.RowFromBottom
和GridEx.RowSpanFromBottom
绑定到它们上面。这些属性更改处理程序将根据这些属性的值和网格中的行数计算Grid.Row
的新值。
一个潜在的问题是,如果你在运行时添加或删除网格中的行,则可能无法正确更新。
public static class GridEx
{
public static readonly DependencyProperty RowFromBottomProperty = DependencyProperty.RegisterAttached("RowFromBottom", typeof(int?), typeof(GridEx), new FrameworkPropertyMetadata(default(int?), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure, OnRowFromBottomChanged));
public static readonly DependencyProperty RowSpanFromBottomProperty = DependencyProperty.RegisterAttached("RowSpanFromBottom", typeof(int?), typeof(GridEx), new FrameworkPropertyMetadata(default(int?), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure, OnRowSpanFromBottomChanged));
private static void OnRowFromBottomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = GetContainingGrid(d);
int? rowFromBottom = (int?) e.NewValue;
int? rowSpanFromBottom = GetRowSpanFromBottom(d);
if (rowFromBottom == null || rowSpanFromBottom == null) return;
int rows = grid.RowDefinitions.Count;
int row = Math.Max(0, Math.Min(rows, rows - rowFromBottom.Value - rowSpanFromBottom.Value));
Grid.SetRow((UIElement) d, row);
}
private static void OnRowSpanFromBottomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = GetContainingGrid(d);
int? rowFromBottom = GetRowFromBottom(d);
int? rowSpanFromBottom = (int?)e.NewValue;
if (rowFromBottom == null || rowSpanFromBottom == null) return;
int rows = grid.RowDefinitions.Count;
int row = Math.Max(0, Math.Min(rows, rows - rowFromBottom.Value - rowSpanFromBottom.Value));
Grid.SetRow((UIElement)d, row);
Grid.SetRowSpan((UIElement)d, rowSpanFromBottom.Value);
}
public static int? GetRowFromBottom(DependencyObject obj)
{
return (int?) obj.GetValue(RowFromBottomProperty);
}
public static void SetRowFromBottom(DependencyObject obj, int? value)
{
obj.SetValue(RowFromBottomProperty, value);
}
public static int? GetRowSpanFromBottom(DependencyObject obj)
{
return (int?)obj.GetValue(RowSpanFromBottomProperty);
}
public static void SetRowSpanFromBottom(DependencyObject obj, int? value)
{
obj.SetValue(RowSpanFromBottomProperty, value);
}
private static Grid GetContainingGrid(DependencyObject element)
{
Grid grid = null;
while (grid == null && element != null)
{
element = LogicalTreeHelper.GetParent(element);
grid = element as Grid;
}
return grid;
}
}
如果您对这里发生的事情有任何疑问,请随时提出。