为什么这个数据绑定不会改变GridUnitType?

时间:2017-11-08 18:25:27

标签: c# wpf gridsplitter gridlength

我的目标是保存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(值)组件,而不更新它的GridUnitType部分。

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

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

1 个答案:

答案 0 :(得分: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>

屏幕截图1:

enter image description here

截屏2:

enter image description here

截屏3:

enter image description here

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

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

左列的

Width.Value与左边界ActualWidth相同,右栏也是如此。你必须抓住两者并保存比例。

更新

我觉得Grid / GridSplitter在日常使用时有点过度工作,但我想要的是另一个导航窗格,所以我最近写了一个SplitterControl,它有两个内容属性并设置网格和分割器,带有样式,在模板中。我还没有把分裂率持续下去,所以我刚才这样做了。

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

业务结束很简单:

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

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上的模板来完成的,这些模板是拆分控制模板的子项。