网格中的扩展器

Cat*_*top 16 wpf layout

毫无疑问,这将是直截了当的,但出于任何理由,我的思绪在其上留下了空白.

我有一个小的,不可调整大小的窗口(325x450),里面有3个扩展器,垂直堆叠.每个Expander都包含一个ItemsControl,它可能包含很多项目,因此需要滚动.

我似乎无法做到的是如何布局扩展器,以便它们扩展以填充任何可用空间而无需将其他元素从屏幕上移开.我可以通过使用网格并将每个扩展器放在一个具有*高度的行中来实现我所追求的目标,但这意味着它们总是占据窗口的1/3,这会破坏扩展器的点:)

我正在努力实现的蹩脚图表:

在此输入图像描述

Fre*_*lad 11

因为你想要的状态这一要求是有点不同寻常ChildrenGrid决定HeightRowDefinition,他们都在.
我真的很喜欢的布局想法,虽然我不敢相信,我从来没有过类似的要求自己.. :)

对于可重用的解决方案,我会使用附加行为Grid.
该行为将订阅附加活动Expander.Expanded,并Expander.Collapsed在事件处理程序,得到正确RowDefinitionGrid.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>
Run Code Online (Sandbox Code Playgroud)

这是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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Rac*_*hel 8

如果你不介意一些代码隐藏,你可以挂钩到Expanded/ Collapsedevents,找到父对象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);
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,那就做到了!事件是膨胀/崩溃顺便说一句:)谢谢! (2认同)