Wpf 折叠网格拆分器?
我有一个WPF页面,上面有一个网格 有三排。第0行包含一个具有Wpf 折叠网格拆分器?,wpf,xaml,gridsplitter,Wpf,Xaml,Gridsplitter,我有一个WPF页面,上面有一个网格 有三排。第0行包含一个具有Height=“*”的GridView。第1行包含一个带有Height=“auto”的GridSplitter。第2行包含一个带有Height=“2*”的详细信息表单 事情是这样的——我有一个按钮,用来切换细节表单的可见性。这很好用。除了只隐藏第2行中的表单外,它不会扩展第0行中的网格以填充空间。我想让按钮切换第0行的GridView以占用所有空间,然后切换回原来的位置 很明显,在行中玩弄表单的可见性并不能达到我想要的效果 但是我需要
Height=“*”
的GridView。第1行包含一个带有Height=“auto”
的GridSplitter。第2行包含一个带有Height=“2*”
的详细信息表单
事情是这样的——我有一个按钮,用来切换细节表单的可见性。这很好用。除了只隐藏第2行中的表单外,它不会扩展第0行中的网格以填充空间。我想让按钮切换第0行的GridView以占用所有空间,然后切换回原来的位置
很明显,在行中玩弄表单的可见性并不能达到我想要的效果
但是我需要玩什么呢?我必须引入一个附加的依赖属性来在我自己的应用程序中处理这个问题:
<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>
然后收听IsVisibleChanged
:
私有静态void OnWatchChanged(DependencyObject对象,
DependencyPropertyChangedEventArgs(附件e)
{
if(obj==null)返回;
if(obj为栅格)
{
var grid=obj作为网格;
var gs=e.NewValue作为GridSplitter;
如果(gs!=null)
{
gs.IsVisibleChanged+=(\u发送方,\u e)=>
{
UpdateGrid(
网格,
(网格拆分器)\ u发送器,
(bool)_e.NewValue,
(bool)_e.OldValue);
};
}
}
}
查看这些更改后,需要保存或恢复正在查看的行或列中的GridLength
值(为简洁起见,我只包括行):
//给定:静态字典值;
私有静态void UpdateGrid(网格网格、网格拆分器、网格拆分器、bool newValue、bool oldValue)
{
如果(新值)
{
//我们又出现了
开关(gridSplitter.ResizeDirection)
{
大小写GridResizeDirection。列:
打破
大小写GridResizeDirection。行:
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(上一个)和&oldValues.ContainsKey(当前))
{
上一个高度=旧值[上一个];
当前高度=旧值[当前];
}
打破
}
}
其他的
{
//我们被藏起来了
开关(gridSplitter.ResizeDirection)
{
大小写GridResizeDirection。列:
打破
大小写GridResizeDirection。行:
int ridx=(int)gridSplitter.GetValue(Grid.RowProperty);
var prev=grid.RowDefinitions.ElementAt(GetPrevious(gridSplitter,ridx));
var curr=grid.RowDefinitions.ElementAt(GetNext(gridSplitter,ridx));
开关(gridSplitter.ResizeBehavior)
{
//天真地假设只有一种类型的崩溃!
案例GridResizeBehavior.PreviousAndCurrent:
oldValues[prev]=上一高度;
prev.Height=新的GridLength(1.0,GridUnitType.Star);
旧值[当前]=当前高度;
当前高度=新网格长度(0.0);
打破
}
打破
}
}
}
剩下的就是GetPrevious
和GetNext
的适当实现:
private static int GetPrevious(GridSplitter GridSplitter,int index)
{
开关(gridSplitter.ResizeBehavior)
{
case GridResizeBehavior.Previous和Next:
案例GridResizeBehavior.PreviousAndCurrent:
回报指数-1;
case GridResizeBehavior.CurrentAndNext:
收益指数;
case GridResizeBehavior.basedAlignment:
违约:
抛出新的NotSupportedException();
}
}
私有静态int GetNext(GridSplitter GridSplitter,int index)
{
开关(gridSplitter.ResizeBehavior)
{
案例GridResizeBehavior.PreviousAndCurrent:
收益指数;
case GridResizeBehavior.Previous和Next:
case GridResizeBehavior.CurrentAndNext:
收益率指数+1;
case GridResizeBehavior.basedAlignment:
违约:
抛出新的NotSupportedException();
}
}
此控件继承的表单GridSpliter可能与您正在寻找的作业相关。我为自己在WPF中使用而改编的Silverlight原始版本的编写工作值得称赞。我发现自己几乎在任何尝试使用GridSplitter的地方都需要此功能,因此它非常方便。假设我有此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=“1*”
,这是行定义的默认设置):
这就是拆分器在用户移动它时隐藏的功能。如果有人想要纯XAML解决方案,我能够想出一种方法,使用样式、设置器和触发器隐藏拆分器和相关行 我为我的样式使用了一个静态资源,该资源被设置为在设置特定的绑定布尔值时更改
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属性的情况下尝试了它,但它没有正确地崩溃。将其添加到中似乎对我起到了作用。我没有意识到我可以拥有行/列定义的样式。美好的谢谢。很好的解决方案!我甚至为last RowDefinition Height属性设置了绑定,而不必在代码中进行绑定。我对实施公认的解决方案犹豫不决
<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>