自分のアプリケーションでこれを処理するには、添付の依存関係プロパティを導入する必要がありました。
<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
andの適切な実装だけ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();
}
}