GridSplitter переопределяет триггер стиля ColumnDefinition?
Я столкнулся с странной проблемой...
Похоже, что изменение размеров столбцов Grid с помощью GridSplitter отключает (или иным образом деактивирует) триггер, определенный в столбце Grid.
Здесь моя настройка:
A Grid имеет 3 столбца, которые определяются следующим образом:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition>
<ColumnDefinition.Style>
<Style>
<Setter Property="ColumnDefinition.Width" Value="Auto"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=OpenItemViewModels.Count}" Value="0">
<Setter Property="ColumnDefinition.Width" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
<ColumnDefinition>
<ColumnDefinition.Style>
<Style>
<Setter Property="ColumnDefinition.Width" Value="4*"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=OpenItemViewModels.Count}" Value="0">
<Setter Property="ColumnDefinition.Width" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
</Grid.ColumnDefinitions>
Ожидается, что, когда в третьем столбце нет элементов, которые составляют ItemsSource для элемента управления, ширина будет назначена второму и третьему столбцам (соответственно, будет размещен элемент GridSplitter и элемент управления вспомогательными элементами).
Это хорошо работает, пока я не касаюсь Splitter (когда все вкладки вспомогательного элемента управления закрыты, остается только первый столбец).
Проблемы начинаются, если я перемещаю разделитель, тем самым эффективно изменяя соотношение между столбцами ## 0 и 2. В таком случае ширина этих столбцов не является reset, когда все элементы в правом элементе управления закрыты.
Я подозреваю, что это связано с тем, что GridSplitter "перегружает" мои определения в XAML.
Кто-нибудь может подтвердить или опровергнуть эту теорию и предложить, как решить эту проблему?
Ответы
Ответ 1
У меня была такая же проблема для определения rowdefinition. Gridsplitter переопределит все, что мы даем в стиле или сеттерах. Его можно решить с помощью анимации (поскольку анимация имеет наивысший приоритет в разрешении значения свойства зависимостей). Сделайте то же самое для третьего столбца.
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition>
<ColumnDefinition.Style>
<Style>
<Setter Property="ColumnDefinition.Width" Value="Auto" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=OpenItemViewModels.Count}" Value="0">
<DataTrigger.EnterActions>
<BeginStoryboard Name="BeginStoryboard1">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Width">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{x:Static GridLength.Auto}" />
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="BeginStoryboard1" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
Ответ 2
Я придумал вспомогательный класс, который помогает решить проблему сбрасываемых столбцов/строк, которые также изменяются с помощью GridSplitter.
public class CollapsibleRowDefinition : RowDefinition
{
public static readonly DependencyProperty IsCollapsedProperty = DependencyProperty.Register(
"IsCollapsed",
typeof(bool),
typeof(CollapsibleRowDefinition),
new FrameworkPropertyMetadata(
false,
(s,e) => { ((CollapsibleRowDefinition) s).IsCollapsed = (bool)e.NewValue; }));
private bool isCollapsed = false;
public CollapsibleRowDefinition()
{
DependencyPropertyDescriptor.FromProperty(RowDefinition.HeightProperty, typeof(RowDefinition)).AddValueChanged(this,
(sender, args) =>
{
if (!this.IsCollapsed)
{
this.ExpandedHeight = this.Height;
}
});
}
public GridLength CollapsedHeight { get; set; }
public GridLength ExpandedHeight { get; set; }
public bool IsCollapsed
{
get { return this.isCollapsed; }
set
{
if (this.isCollapsed != value)
{
this.isCollapsed = value;
this.Height = value ? this.CollapsedHeight : this.ExpandedHeight;
}
}
}
}
Разметка затем идет следующим образом
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="5"/>
<c:CollapsibleRowDefinition CollapsedHeight="20" ExpandedHeight="*" IsCollapsed="{Binding ElementName=Btn_BottomCollapse, Path=IsChecked}"/>
</Grid.RowDefinitions>
<GridSplitter Grid.Row="2" HorizontalAlignment="Stretch"
IsEnabled="{Binding ElementName=Btn_BottomCollapse, Path=IsChecked}"/>
Ответ 3
У меня была та же проблема...
Единственное, что мне удалось выработать, было примерно так:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" x:Name="theColumn"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Expander Grid.Column="0" x:Name="theExpander" Expander.Collapsed="theExpander_Collapsed">
...
</Expander>
<GridSplitter Grid.Column="0" HorizontalAlignment="Right" Width="5">
<GridSplitter.Style>
<Style TargetType="{x:Type GridSplitter}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=theExpander, Path=IsExpanded}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</GridSplitter.Style>
</GridSplitter>
<Grid Grid.Column="1">
...
</Grid>
</Grid>
И код позади:
private void theExpander_Collapsed(object sender, RoutedEventArgs e)
{
theColumn.Width = GridLength.Auto;
}
Это не так, как я бы предпочел сделать это, но попытка использовать триггер стиля для определения столбца просто не работает.