【问题标题】:Why does this data binding not change the GridUnitType?为什么这个数据绑定不改变 GridUnitType?
【发布时间】:2018-04-21 13:46:39
【问题描述】:

我的目标是保存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 像素)。

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

【问题讨论】:

    标签: c# wpf gridsplitter gridlength


    【解决方案1】:
    <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:

    屏幕截图 2:

    屏幕截图 3:

    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 上切换模板来完成的,它是拆分控件模板的子级。

    【讨论】:

    • 换句话说,仅此值是不够的。我必须捕获并恢复两个面板的宽度才能做到这一点。
    • @DonBoitnott 要么这样,要么放弃按比例调整大小,让左(或右)列按单位调整大小,并制作另一列*
    猜你喜欢
    • 2010-10-26
    • 2014-05-31
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多