我有一个WPF页面,上面有一个网格。
一共有三排。行0包含带Height="*"的GridView。行%1包含一个带Height="auto"的GridSplitter。第2行包含一个带有Height="2*"的详细信息表单。
事情是这样的-我有一个按钮,用来切换细节表单的可见性。这就很好用了。除了它只隐藏了第2行中的表单之外,它不会展开第0行中的网格来填充空格。我想要的是让按钮切换到第0行中的GridView以占据所有空间,然后切换回原来的位置。
显然,在行中玩弄表单的可见性不会达到我想要的效果。
但是我需要玩些什么呢?
发布于 2012-09-19 02:53:36
我不得不引入一个附加的依赖属性来在我自己的应用程序中处理这个问题:
<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上定义一个合适的附加属性
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
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值(为简洁起见,我只包括行):
// 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;
}
}
}剩下的就是GetPrevious和GetNext的合适实现了
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();
}
}发布于 2018-10-30 07:58:39
如果有人想要一个纯粹的XAML解决方案,我能够变出一种方法,使用样式、setter和触发器隐藏拆分器和相关行。
我为我的样式使用了一个静态资源,它被设置为在设置了特定的绑定布尔值时更改Height和MaxHeight。
<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>我只需将该样式应用于相关的行定义,它就像一个护身符:
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Style="{StaticResource showRow}"/>
<RowDefinition Style="{StaticResource showRow}"/>
</Grid.RowDefinitions>值得注意的是,我在没有使用MaxHeight属性的情况下尝试了它,它不能正确地折叠。将它添加进来似乎对我来说已经完成了这个戏法。
发布于 2015-12-09 19:12:56
假设我有这样的XAML布局:
<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" ):
MyGrid.RowDefinitions[2].Height = new GridLength(0);并使用以下代码解开它(相当于在XAML中设置Height="1*",这是RowDefinition的默认设置):
MyGrid.RowDefinitions[2].Height = new GridLength(1, GridUnitType.Star);这就是当用户移动拆分器时拆分器所做的事情。
https://stackoverflow.com/questions/12483017
复制相似问题