首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF:崩溃GridSplitter?

WPF:崩溃GridSplitter?
EN

Stack Overflow用户
提问于 2012-09-19 02:40:15
回答 4查看 8.7K关注 0票数 7

我有一个WPF页面,上面有一个网格。

一共有三排。行0包含带Height="*"的GridView。行%1包含一个带Height="auto"的GridSplitter。第2行包含一个带有Height="2*"的详细信息表单。

事情是这样的-我有一个按钮,用来切换细节表单的可见性。这就很好用了。除了它只隐藏了第2行中的表单之外,它不会展开第0行中的网格来填充空格。我想要的是让按钮切换到第0行中的GridView以占据所有空间,然后切换回原来的位置。

显然,在行中玩弄表单的可见性不会达到我想要的效果。

但是我需要玩些什么呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-09-19 02:53:36

我不得不引入一个附加的依赖属性来在我自己的应用程序中处理这个问题:

代码语言:javascript
复制
<Grid c:GridSplitterController.Watch="{Binding ElementName=GS_DetailsView}">
    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="200" />
    </Grid.RowDefinitions>

    <SomeControl Grid.Row="0" />

    <GridSplitter x:Name="GS_DetailsView"
                  Height="4"
                  Grid.Row="1"
                  VerticalAlignment="Top"
                  HorizontalAlignment="Stretch"
                  ResizeBehavior="PreviousAndCurrent"
                  ResizeDirection="Rows"
                  Visibility="{Binding ShowDetails,
                                       Converter={StaticResource boolvis}}" />

    <OtherControl Grid.Row="1"
                  Margin="0,4,0,0"
                  Visibility="{Binding ShowDetails,
                                       Converter={StaticResource boolvis}}" />
</Grid>

首先在DependencyObject上定义一个合适的附加属性

代码语言:javascript
复制
public static GridSplitter GetWatch(DependencyObject obj)
{
    return (GridSplitter)obj.GetValue(WatchProperty);
}

public static void SetWatch(DependencyObject obj, GridSplitter value)
{
    obj.SetValue(WatchProperty, value);
}

public static readonly DependencyProperty WatchProperty =
    DependencyProperty.RegisterAttached(
        "Watch",
        typeof(GridSplitter),
        typeof(DependencyObject),
        new UIPropertyMetadata(null, OnWatchChanged));

然后监听IsVisibleChanged

代码语言:javascript
复制
private static void OnWatchChanged(DependencyObject obj,
    DependencyPropertyChangedEventArgs e)
{
    if (obj == null) return;
    if (obj is Grid)
    {
        var grid = obj as Grid;
        var gs = e.NewValue as GridSplitter;
        if (gs != null)
        {
            gs.IsVisibleChanged += (_sender, _e) =>
                {
                    UpdateGrid(
                        grid,
                        (GridSplitter)_sender,
                        (bool)_e.NewValue,
                        (bool)_e.OldValue);
                };
        }
    }
}

一旦您监视这些更改,您需要保存或恢复您正在监视的行或列中的GridLength值(为简洁起见,我只包括行):

代码语言:javascript
复制
// Given: static Dictionary<DependencyObject, GridLength> oldValues;
private static void UpdateGrid(Grid grid, GridSplitter gridSplitter, bool newValue, bool oldValue)
{
    if (newValue)
    {
        // We're visible again
        switch (gridSplitter.ResizeDirection)
        {
        case GridResizeDirection.Columns:
            break;
        case GridResizeDirection.Rows:
            int ridx = (int)gridSplitter.GetValue(Grid.RowProperty);
            var prev = grid.RowDefinitions.ElementAt(GetPrevious(gridSplitter, ridx));
            var curr = grid.RowDefinitions.ElementAt(GetNext(gridSplitter, ridx));
            if (oldValues.ContainsKey(prev) && oldValues.ContainsKey(curr))
            {
                prev.Height = oldValues[prev];
                curr.Height = oldValues[curr];
            }

            break;
        }
    }
    else
    {
        // We're being hidden
        switch (gridSplitter.ResizeDirection)
        {
        case GridResizeDirection.Columns:
            break;
        case GridResizeDirection.Rows:
            int ridx = (int)gridSplitter.GetValue(Grid.RowProperty);
            var prev = grid.RowDefinitions.ElementAt(GetPrevious(gridSplitter, ridx));
            var curr = grid.RowDefinitions.ElementAt(GetNext(gridSplitter, ridx));
            switch (gridSplitter.ResizeBehavior)
            {
                // Naively assumes only one type of collapsing!
                case GridResizeBehavior.PreviousAndCurrent:
                    oldValues[prev] = prev.Height;
                    prev.Height = new GridLength(1.0, GridUnitType.Star);

                    oldValues[curr] = curr.Height;
                    curr.Height = new GridLength(0.0);
                    break;
            }
            break;
        }
    }
}

剩下的就是GetPreviousGetNext的合适实现了

代码语言:javascript
复制
private static int GetPrevious(GridSplitter gridSplitter, int index)
{
    switch (gridSplitter.ResizeBehavior)
    {
        case GridResizeBehavior.PreviousAndNext:
        case GridResizeBehavior.PreviousAndCurrent:
            return index - 1;
        case GridResizeBehavior.CurrentAndNext:
            return index;
        case GridResizeBehavior.BasedOnAlignment:
        default:
            throw new NotSupportedException();
    }
}

private static int GetNext(GridSplitter gridSplitter, int index)
{
    switch (gridSplitter.ResizeBehavior)
    {
        case GridResizeBehavior.PreviousAndCurrent:
            return index;
        case GridResizeBehavior.PreviousAndNext:
        case GridResizeBehavior.CurrentAndNext:
            return index + 1;
        case GridResizeBehavior.BasedOnAlignment:
        default:
            throw new NotSupportedException();
    }
}
票数 4
EN

Stack Overflow用户

发布于 2018-10-30 07:58:39

如果有人想要一个纯粹的XAML解决方案,我能够变出一种方法,使用样式、setter和触发器隐藏拆分器和相关行。

我为我的样式使用了一个静态资源,它被设置为在设置了特定的绑定布尔值时更改HeightMaxHeight

代码语言:javascript
复制
<Style x:Key="showRow" TargetType="{x:Type RowDefinition}">
  <Style.Setters>
    <Setter Property="Height" Value="*"/>
  </Style.Setters>
  <Style.Triggers>
    <DataTrigger Binding="{Binding MyShowRowBool}" Value="False">
      <DataTrigger.Setters>
        <Setter Property="Height" Value="0"/>
        <Setter Property="MaxHeight" Value="0"/>
      </DataTrigger.Setters>
    </DataTrigger>
  </Style.Triggers>
</Style>

我只需将该样式应用于相关的行定义,它就像一个护身符:

代码语言:javascript
复制
<Grid.RowDefinitions>
  <RowDefinition Height="*"/>
  <RowDefinition Style="{StaticResource showRow}"/>
  <RowDefinition Style="{StaticResource showRow}"/>
</Grid.RowDefinitions>

值得注意的是,我在没有使用MaxHeight属性的情况下尝试了它,它不能正确地折叠。将它添加进来似乎对我来说已经完成了这个戏法。

票数 14
EN

Stack Overflow用户

发布于 2015-12-09 19:12:56

假设我有这样的XAML布局:

代码语言:javascript
复制
  <Grid Name="MyGrid">
      <Grid.RowDefinitions>
          <RowDefinition />
          <RowDefinition Height="Auto" />
          <RowDefinition />
      </Grid.RowDefinitions>
      <MyControl1 ... Grid.Row="0" />
      <GridSplitter Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Stretch" ShowsPreview="True" Height="5" />
      <MyControl2 ... Grid.Row="2" />
  </Grid>

然后我可以用下面的代码隐藏第二个控件(折叠拆分器)(相当于在XAML中设置Height="0" ):

代码语言:javascript
复制
  MyGrid.RowDefinitions[2].Height = new GridLength(0);

并使用以下代码解开它(相当于在XAML中设置Height="1*",这是RowDefinition的默认设置):

代码语言:javascript
复制
  MyGrid.RowDefinitions[2].Height = new GridLength(1, GridUnitType.Star);

这就是当用户移动拆分器时拆分器所做的事情。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12483017

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档