tôi đã giới thiệu một phụ thuộc tài sản gắn liền để xử lý này trong ứng dụng của riêng tôi:
<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>
Đầu tiên xác định một tài sản gắn liền phù hợp trên một 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));
Sau đó lắng nghe 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);
};
}
}
}
Khi bạn đang xem thay đổi e, bạn cần phải lưu hoặc khôi phục lại GridLength
giá trị từ hàng hoặc cột mà bạn đang theo dõi (cho ngắn gọn tôi chỉ bao gồm Rows):
// 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;
}
}
}
Tất cả những gì còn lại là một việc thực hiện phù hợp của GetPrevious
và 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();
}
}
Phải là một câu trả lời được chấp nhận thực sự. Công việc tốt đẹp! –