增加 WPF GridSplitter 鼠标抓取阈值

9

是否可以增加网格分隔器的可抓取距离?

我的分隔器只有1像素宽。我希望能够从更远的距离抓住分隔器。

现在我必须将鼠标指向精确的1像素线才能抓住它。

并且分隔器仍然必须是1像素宽。

3个回答

20
你可以改变GridSplitter的实际尺寸,同时使其看起来更小。这将为你提供一个7像素宽度的区域来抓取它,而显示为1像素:
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="1"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <GridSplitter Grid.Column="1"
                  Margin="-3,0"
                  BorderThickness="3,0"
                  BorderBrush="Transparent"
                  HorizontalAlignment="Stretch" />
</Grid>

该示例使用将分隔符放在它自己的列中的方法,但是如果它在共享列中左对齐或右对齐,则相同的原则也适用。


4
这是正确的,但我必须更改网格分隔器的ZIndex,因为它的右侧被DockPanel遮挡了。 - ErikTJ
Margin="-3,0" 的目的是什么?您想让水平分隔符左对齐在7像素区域内而不是居中吗? - Winter Dragoness
负边距在布局中创建额外的空间,以便3像素透明边框填充。如果没有这些,分隔器只能在1像素列中呈现。 - John Bowen
值得注意的是,BorderBrush="Transparent" 是关键。如果将其保留为默认值(即“无刷子”),则此方法不起作用。 - Anthony Nichols
澄清@ErikTJ的评论:您需要将GridSplitter放置在网格中的其他元素之后(源代码中较低的位置),以便它不会被它们覆盖。 - Bouke Versteegh

3

我知道这是一个古老的问题,但我还是想添加我的答案。经过大量实验,以下方法似乎非常适用于1像素宽的Gridsplitter

<ControlTemplate x:Key="gs0" TargetType="{x:Type GridSplitter}">
    <Border Margin="-5,0" Background="Transparent">
        <TextBlock Width="1"  Background="Green" />
    </Border>
</ControlTemplate>

以下代码已经过测试:

Grid HorizontalAlignment="Left"  >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition Width="1"/>
        <ColumnDefinition Width="200"/>
    </Grid.ColumnDefinitions>

<Grid Grid.Column="0">
    ....
</Grid>

<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" Template ="{StaticResource gs0}"/>

没有模板时,“鼠标抓取区域”为1个像素。但是通过使用上述模板设置后,它增加到了大约7个像素,这是正确的。相同的代码可以通过调整Textblock WidthBorder MarginColumnDefinition Width来适应2个或更多像素宽度的线条。您可以将鼠标抓取区域设置得非常大,但问题在于增加仅发生在左侧;它不居中于线条,随着增加变得越来越明显。但对于窄线,这是一种轻松增加鼠标抓取到可用状态的方法。

我正在使用2像素宽的Gridsplitters并使用样式设置IsMouseOver属性等:

<Style TargetType="{x:Type GridSplitter}">
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="Background" Value="LightGray"/>
    <Setter Property="OpacityMask" Value="{StaticResource gs_OpacityMask}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type GridSplitter}">
                <Border Margin="-3,0" Background="Transparent">
                    <TextBlock x:Name="tb" Width="2"  Background="{TemplateBinding Background}" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" TargetName="tb" Value="#FF0B75FD" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

重要提示:在这种情况下,ColumnDefinition Width需要设置为3或4,以适应2像素宽度的线条。


2

我无法使John Bowen的解决方案起作用。它看起来像是可以工作,但似乎分隔器只有1个像素的可抓取空间。

最终我做了这个:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Stackpanel Grid.Row="0"/>
    <GridSplitter
        Grid.Row="1"
        HorizontalAlignment="Stretch"
        BorderBrush="DarkGray"
        Height="6"
        Background="Transparent"
        BorderThickness="0,1,0,0"
        Margin="0,0,0,-4"/>
    <Stackpanel Grid.Row="2"/>
</Grid>

这使分隔器的高度为6个像素,但仅显示1个像素的顶部边框线。您需要使用负底边距((Height / 2) - 1)来将顶部边距线居中于行的中间。

否则,背景是透明的,否则您将看到6个像素的灰色或默认颜色。如果您使用Blend深入控件模板GridSplitter,您会发现它只是一个带有边框的样式化矩形或类似于此类的东西。


这种技术的问题在于它将灰线放置在6像素区域的顶部,您可以在该区域中抓住灰线。您确定您没有忘记将John的垂直答案翻转为水平的某些值吗?对我有用的是(5像素区域可供抓取,灰线位于区域中心):<GridSplitter Height="5" BorderThickness="0,2" BorderBrush="Transparent" Background="DarkGray" HorizontalAlignment="Stretch" /> - Winter Dragoness

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接