GridSplitter 在移动到外部资源(UserControl)时表现不同

GridSplitter acts differently when moved to external resource (UserControl)

由于我的 WPF 应用程序多次使用 GridSplitter,我想将 XAML 片段提取到单独的 UserControl.

当然,使用ResourceDictionary会更好。但是那样的话,我只能为拆分器的内容定义一个 ControlTemplate,然后在 Template- 属性中使用它 - 这样就无法定义所有这些 GridSplitter 属性一次又一次连续使用它们。

GridSplitter UserControl, GridSplitter.xaml:

<GridSplitter HorizontalAlignment="Stretch" Margin="3" ResizeBehavior="PreviousAndNext"
              ResizeDirection="Columns" VerticalAlignment="Stretch">
  <GridSplitter.Template>
    <ControlTemplate TargetType="{x:Type GridSplitter}">
      <Grid>
        <Button Content="⁞" />
        <Rectangle Fill="#00FFFFFF" />
      </Grid>
    </ControlTemplate>
  </GridSplitter.Template>
</GridSplitter>

MainWindow.xaml中的用法:

<Window
         (...)
         xmlns:uc="clr-namespace:Yoda.Frontend.Resources"
         (...)>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition MinWidth="100" Width="200" />
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition MinWidth="400" Width="*" />
    </Grid.ColumnDefinitions>
    <!-- (...) -->
    <uc:GridSplitter Grid.Column="1" />
    <!-- (...) -->
  </Grid>
    <!-- (...) -->
</Window>

使用上述代码的结果是无法向任何方向移动的拆分器。

但是,使用上面提到的 ResourceDictionary 字典方法,我得到了一个可移动的 GridSplitter
但是尽管直接在 MainWindow.xaml 中完美地工作,它只调整第三个网格列的大小。

当然,在使用 GridSplitter 时不建议设置 Width。但是,为什么只要拆分器在主 window 中定义,它就可以工作,而只有在用作 UserControl 时才会这样做?以及如何在 MVVM 中解决这个问题,没有代码隐藏方式?

如果你只是想要一个漂亮的分离器,你可以使用这个代码:

<Grid.ColumnDefinitions>
     <ColumnDefinition MinWidth="100" Width="Auto" />
     <ColumnDefinition MinWidth="20" Width="Auto" />
     <ColumnDefinition MinWidth="400" Width="Auto" />
</Grid.ColumnDefinitions>
<!-- (...) -->
<GridSplitter Grid.Column="1" Background="Gray" HorizontalAlignment="Stretch"
              VerticalAlignment="Stretch" />
<TextBlock Text="⁞" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"
           IsHitTestVisible="False" />
<!-- (...) -->

另一种解决方案是将 ControlTemplate 定义为资源,然后将其用于 GridSplitter:

<Window.Resources>
    <ControlTemplate TargetType="{x:Type GridSplitter}" x:Key="gridSplitter">
        <Grid Background="Transparent">
            <Button Content="⁞" IsHitTestVisible="False" />
            <Rectangle Fill="#00FFFFFF" IsHitTestVisible="False" />
        </Grid>
    </ControlTemplate>
</Window.Resources>
<Grid>
    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Blue">
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="100" Width="Auto" />
            <ColumnDefinition MinWidth="20" Width="Auto" />
            <ColumnDefinition MinWidth="400" Width="Auto" />
        </Grid.ColumnDefinitions>
        <!-- (...) -->
        <GridSplitter Grid.Column="1" Template="{StaticResource gridSplitter}" />
        <!-- (...) -->
    </Grid>
    <!-- (...) -->
</Grid>

如果您真的想在拆分器模板中使用设置属性,还有一个解决方案:使用样式来添加这些属性。它看起来像这样:

<Window.Resources>
    <ControlTemplate TargetType="{x:Type GridSplitter}" x:Key="gridSplitter">
        <Grid Background="Transparent">
            <Button Content="⁞" IsHitTestVisible="False"/>
            <Rectangle Fill="#00FFFFFF" IsHitTestVisible="False"/>
        </Grid>
    </ControlTemplate>
    <Style TargetType="{x:Type GridSplitter}" x:Key="styleGridSplitter">
        <Setter Property="Template" Value="{StaticResource gridSplitter}" />
        <Setter Property="ResizeBehavior" Value="PreviousAndNext" />
        <Setter Property="ResizeDirection" Value="Columns" />
        <Setter Property="VerticalAlignment" Value="Stretch" />
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="Margin" Value="3" />
    </Style>
</Window.Resources>
<Grid>
    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Blue">
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="100" Width="Auto" />
            <ColumnDefinition MinWidth="20" Width="Auto" />
            <ColumnDefinition MinWidth="400" Width="Auto" />
        </Grid.ColumnDefinitions>
        <!-- (...) -->
        <GridSplitter Grid.Column="1" Style="{StaticResource styleGridSplitter}"/>
        <!-- (...) -->
    </Grid>
    <!-- (...) -->
</Grid>