Экспандеры в сетке - PullRequest
       1

Экспандеры в сетке

16 голосов
/ 07 сентября 2011

Без сомнения, это будет прямолинейно, но по какой-то причине мой разум рисует на этом пробел.

У меня есть небольшое, не изменяемого размера окно (325x450), которое имеет3 расширителя в нем, уложены вертикально.Каждый Expander содержит ItemsControl, который потенциально может содержать много элементов и поэтому должен прокручиваться.

Похоже, я не могу понять, как правильно расположить расширители так, чтобы они расширялись, заполняя любое доступное пространство, не отталкивая другие элементы от экрана.Я могу в некотором роде достичь того, чего я добиваюсь, используя Grid и помещая каждый расширитель в ряд с высотой *, но это означает, что они всегда занимают 1/3 окна каждое, что побеждает точку Расширителя :)

Дрянная диаграмма того, чего я пытаюсь достичь:

enter image description here

Ответы [ 2 ]

11 голосов
/ 07 сентября 2011

Это требование немного необычно, потому что вы хотите, чтобы состояние Children в Grid определяло Height из RowDefinition, в котором они находятся.
Мне действительно нравитсяИдея компоновки, хотя и я не могу поверить, что у меня никогда не было аналогичных требований.подпишется на присоединенные события Expander.Expanded и Expander.Collapsed и в обработчиках событий получит право RowDefinition из Grid.GetRow и обновит Height соответственно.Это работает так:

<Grid ex:GridExpanderSizeBehavior.SizeRowsToExpanderState="True">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Expander Grid.Row="0" ... />
    <Expander Grid.Row="1" ... />
    <Expander Grid.Row="2" ... />
    <!-- ... -->
</Grid>

А вот GridExpanderSizeBehavior

public class GridExpanderSizeBehavior
{
    public static DependencyProperty SizeRowsToExpanderStateProperty =
        DependencyProperty.RegisterAttached("SizeRowsToExpanderState",
                                            typeof(bool),
                                            typeof(GridExpanderSizeBehavior),
                                            new FrameworkPropertyMetadata(false, SizeRowsToExpanderStateChanged));
    public static void SetSizeRowsToExpanderState(Grid grid, bool value)
    {
        grid.SetValue(SizeRowsToExpanderStateProperty, value);
    }
    private static void SizeRowsToExpanderStateChanged(object target, DependencyPropertyChangedEventArgs e)
    {
        Grid grid = target as Grid;
        if (grid != null)
        {
            if ((bool)e.NewValue == true)
            {
                grid.AddHandler(Expander.ExpandedEvent, new RoutedEventHandler(Expander_Expanded));
                grid.AddHandler(Expander.CollapsedEvent, new RoutedEventHandler(Expander_Collapsed));
            }
            else if ((bool)e.OldValue == true)
            {
                grid.RemoveHandler(Expander.ExpandedEvent, new RoutedEventHandler(Expander_Expanded));
                grid.RemoveHandler(Expander.CollapsedEvent, new RoutedEventHandler(Expander_Collapsed));
            }
        }
    }
    private static void Expander_Expanded(object sender, RoutedEventArgs e)
    {
        Grid grid = sender as Grid;
        Expander expander = e.OriginalSource as Expander;
        int row = Grid.GetRow(expander);
        if (row <= grid.RowDefinitions.Count)
        {
            grid.RowDefinitions[row].Height = new GridLength(1.0, GridUnitType.Star); 
        }
    }
    private static void Expander_Collapsed(object sender, RoutedEventArgs e)
    {
        Grid grid = sender as Grid;
        Expander expander = e.OriginalSource as Expander;
        int row = Grid.GetRow(expander);
        if (row <= grid.RowDefinitions.Count)
        {
            grid.RowDefinitions[row].Height = new GridLength(1.0, GridUnitType.Auto);
        }
    }
}
8 голосов
/ 07 сентября 2011

Если вы не возражаете против небольшого кода, вы можете подключиться к событиям Expanded / Collapsed, найти родительский Grid, получить RowDefinition для расширителя и установить значение равно *, если его развернуть, или Auto, если нет.

Например,

Expander ex = sender as Expander;
Grid parent = FindAncestor<Grid>(ex);
int rowIndex = Grid.GetRow(ex);

if (parent.RowDefinitions.Count > rowIndex && rowIndex >= 0)
    parent.RowDefinitions[rowIndex].Height = 
        (ex.IsExpanded ? new GridLength(1, GridUnitType.Star) : GridLength.Auto);

И метод FindAncestor определяется следующим образом:

public static T FindAncestor<T>(DependencyObject current)
where T : DependencyObject
{
    // Need this call to avoid returning current object if it is the 
    // same type as parent we are looking for
    current = VisualTreeHelper.GetParent(current);

    while (current != null)
    {
        if (current is T)
        {
            return (T)current;
        }
        current = VisualTreeHelper.GetParent(current);
    };
    return null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...