1

我的目标是保存一个GridSplitter位置以供以后调用。拆分器位于一个Grid控件内,该控件具有如此定义的三列:

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="{Binding GridPanelWidth, Mode=TwoWay}" />
    <ColumnDefinition Width="3" />  <!--splitter itself is in this column-->
    <ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>

该属性GridPanelWidth在视图模型中以这种方式定义:

private GridLength _gridPanelWidth = new GridLength(1, GridUnitType.Star);
public GridLength GridPanelWidth
{
    get { return _gridPanelWidth; }
    set
    {
        if (_gridPanelWidth != value)
            SetProperty(ref _gridPanelWidth, value, () => GridPanelWidth);
    }
}

我遇到的问题是,当拆分器移动时,绑定只更新Double绑定属性的 (Value) 组件,而不是GridUnitType它的一部分。

示例:属性默认为1*. 用户拖动拆分器,值变为354*,而不仅仅是354。那么,在恢复值时,它是巨大的(354 倍,而不是 354 像素)。

为什么会发生这种情况,你会怎么做?

4

1 回答 1

3
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{Binding GridPanelWidth, Mode=TwoWay}" />
        <ColumnDefinition Width="4" />
        <!--splitter itself is in this column-->
        <ColumnDefinition x:Name="RightColumn" Width="2*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Border
        BorderBrush="Gray"
        BorderThickness="1"
        Grid.Column="0"
        Grid.Row="0"
        />

    <GridSplitter
        Background="SteelBlue"
        ResizeBehavior="PreviousAndNext"
        ResizeDirection="Columns"
        VerticalAlignment="Stretch"
        HorizontalAlignment="Stretch"
        ShowsPreview="False"
        Grid.Column="1"
        Grid.Row="0"
        />

    <Border
        BorderBrush="Gray"
        BorderThickness="1"
        Grid.Column="2"
        Grid.Row="0"
        />

    <StackPanel
        Grid.Row="1"
        Grid.ColumnSpan="3"
        Grid.Column="0"
        >
        <TextBlock>
            <Run>GridPanelWidth: </Run>
            <Run Text="{Binding GridPanelWidth.Value, Mode=OneWay}" />
            <Run Text="{Binding GridPanelWidth.GridUnitType, Mode=OneWay}" />
        </TextBlock>
        <TextBlock>
            <Run>RightColumn.Width: </Run>
            <Run Text="{Binding Width.Value, ElementName=RightColumn, Mode=OneWay}" />
            <Run Text="{Binding Width.GridUnitType, ElementName=RightColumn, Mode=OneWay}" />
        </TextBlock>
    </StackPanel>
</Grid>

截图一:

在此处输入图像描述

截图二:

在此处输入图像描述

截图 3:

在此处输入图像描述

Res ipsa loquitor,就我而言,但只是为了安全起见:

因为父级可能会调整大小,所以网格拆分器会更改两列之间的比例,同时保留GridUnitType.Star每个列的比例,以便在调整父级大小时,比例自然会保持不变。这保留了 XAML 中初始宽度值的意图。

Width.Value左列结果与左边框ActualWidth相同,右列也是如此。你必须抓住两者并保存比率。

更新

当我想要的只是另一个导航窗格时,我发现Grid/对日常使用有点过度设计,所以我最近编写了一个具有两个内容属性并在模板中设置网格和拆分器的样式。我还没来得及让分流比保持不变,所以我刚刚这样做了。GridSplitterSplitterControl

我所做的相当痛苦,因为控件是可配置的,而且代码不是那么好,但如果你有兴趣,我可以分享。

业务端很简单:

当列调整大小时,设置一个标志来阻止递归和

PaneRatio = _PART_ContentColumn.Width.Value / _PART_NavColumn.Width.Value;

更改时PaneRatio,如果它不是由列大小更改处理程序设置的

_PART_NavColumn.Width = new GridLength(1, GridUnitType.Star);
_PART_ContentColumn.Width = new GridLength(PaneRatio, GridUnitType.Star);

在实践中,导航器/内容列可以交换,或者它们可以是行。这两者都是通过HeaderedContentControl在拆分控件模板的子级上切换模板来完成的。

于 2017-11-08T18:46:56.103 回答