Usted debe ser capaz de hacer esto sin tener que crear una costumbre o control de usuario mediante el uso de las propiedades asociadas.
Aquí es una clase que creo que debería ser capaz de hacer lo que quiera. En lugar de vincular los valores de Grid.Row
y Grid.RowSpan
a su fila y altura, vincule GridEx.RowFromBottom
y GridEx.RowSpanFromBottom
. Los manejadores de cambio de propiedad para estas propiedades calcularán el nuevo valor de Grid.Row
según los valores de esas propiedades y el número de filas en la grilla.
Un problema potencial es que esto no puede actualizar correctamente si va a añadir o restar filas de la cuadrícula en tiempo de ejecución.
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;
}
}
Si usted tiene alguna pregunta acerca de lo que está pasando aquí, no dude en preguntar.
¿Podría dar un ejemplo que ilustra por qué lo necesita? – sll
Agregué un ejemplo – Robert
diagrama genial :) – Aftnix