有人知道用于使用生成单元格对Grid列进行大小调整的算法吗?(WPF)

Phi*_*ght 2 wpf grid

当您的子元素始终包含在单个网格单元格中时(即没有列/行跨越),使用WPF网格控件很容易.固定宽度的列保持所请求的固定宽度,自动列的大小确实与列中最宽的单元格一样宽.星列根据其相对星值共享任何剩余空间.一切都很简单.

但是一旦你有一个跨越两列或更多列的单元格,列的宽度变得更加复杂,并且实际上看起来反直觉.这是我的意思的一个简单例子.我们可以定义两列,第一列为auto,第二列为30像素.

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
Run Code Online (Sandbox Code Playgroud)

现在我们定义一个跨越两列的按钮,恰好以80像素宽度进行测量.(在我的机器上使用我的字体和主题设置等...)

<Button Grid.ColumnSpan="2" Content="QWERTYUIOP"/>
Run Code Online (Sandbox Code Playgroud)

我们需要在两个生成列上分配按钮的80像素宽度.鉴于第二列固定为30,我预计将为该列分配30,剩余的50将转到第一列.因为第一列是自动的,所以看起来很明显.

但不是.如果你在实践中尝试这个,你会发现第一列是0像素而第二列已经变成完整的80.即使第二列被定义为固定,因此不应该变得更大,它会拉伸到整个宽度的按钮.也许我在这里遗漏了一些东西,但这对我来说似乎不合逻辑.

所以对我的实际问题.是否对Grid控件用于执行此计算的逻辑有完整描述,以便我可以完全理解它是如何工作的?我搜索过MSDN和Google,但没有找到任何描述生成元素如何影响列宽的内容.

Mar*_*ris 5

老实说,当我读到这篇文章时,我不相信你,所以我不得不自己去测试,确实你是对的.我不认为你有任何运气找到规则,因为进一步的调查让我相信它是WPF网格中的一个错误.我进行了一些测试,看看我是否可以确定这种行为,但如果你只是想知道最后的结论,请随意翻阅以下的dia骂.

对不起,如果结果不清楚,那就是我把它们写成工作的方式.前三个数字是我为每列放入的大小值,其余是结果大小.

测试1:

<Grid Height="300" Width="300">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
    </Grid.ColumnDefinitions>
    <Button Grid.ColumnSpan="2" Content="QWERTYUIOP"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)

网格300 X 300托管一个80像素宽的控制器.网格有三列,控件跨越列0和1:

30  , auto, *    - column 0 - 80,  column 1 - 0,  column 2 - 220
auto, auto, *    - column 0 - 40,  column 1 - 40, column 2 - 220
auto, 30  , *    - column 0 - 0,   column 1 - 80, column 2 - 220
*   , 30  , *    - column 0 - 135, column 1 - 30, column 2 - 135
*   , 30  , 26*  - column 0 - 10,  column 1 - 30, column 2 - 260
*   , auto, *    - column 0 - 150, column 1 - 0,  column 2 - 150
*   , auto, 30*  - column 0 - 10,  column 1 - 0,  column 2 - 290
30  , 30  , *    - column 0 - 30,  column 1 - 30, column 2 - 240
*   , *   , 28*  - column 0 - 10,  column 1 - 10, column 2 - 280
Run Code Online (Sandbox Code Playgroud)

因此,我可以提出一些规则:

  1. 如果元素跨越自动大小的单元格和非自动大小的单元格,则自动调整大小的单元格将调整为0
  2. 如果元素跨越固定单元格和自动单元格,则固定单元格的宽度将增加到可以包含整个对象的最小值
  3. 如果元素跨越*大小的单元格和自动调整大小的单元格,则*大小的单元格将具有其预期大小
  4. 如果一个元素跨越两个自动调整大小的单元格,它们将展开以适合该对象并且宽度相等
  5. 如果元素跨越不包含自动单元格的单元格,则单元格将具有其预期大小

测试2:

<Grid ShowGridLines="True" Height="300" Width="300">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Button Grid.ColumnSpan="2" Content="QWERTYUIOP"/>
    <Button Grid.Row="1" Grid.Column="1" Content="QWERTYUIOP"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)

网格300 X 300,其中3列托管一个控件80像素宽,第0行和第2行第0行,第二个控件仅80行像素,第1行第1列

30  , auto, *    - column 0 - 30,  column 1 - 80, column 2 - 190
auto, auto, *    - column 0 - 0,   column 1 - 80, column 2 - 220
auto, 30  , *    - column 0 - 0,   column 1 - 80, column 2 - 220 (*)
*   , 30  , *    - column 0 - 135, column 1 - 30, column 2 - 135
*   , 30  , 26*  - column 0 - 10,  column 1 - 30, column 2 - 260
*   , auto, *    - column 0 - 110, column 1 - 80, column 2 - 110
*   , auto, 30*  - column 0 - 7,   column 1 - 80, column 2 - 213
30  , 30  , *    - column 0 - 30,  column 1 - 30, column 2 - 240
*   , *   , 28*  - column 0 - 10,  column 1 - 10, column 2 - 280
Run Code Online (Sandbox Code Playgroud)

(*)这不完全是发生的事情.第1列设置为80,但仅绘制部分非跨越元素.我使用按钮作为我的元素,非跨越按钮的chrome填充了80像素宽的第一列,但文本被修剪为30像素的大小.基本上它是完全拧紧的.

从这个测试我可以添加两个规则:

  1. 如果在跨度中使用自动列并且可以从某个位置获取其大小,则它将按预期运行
  2. 如果在跨度中使用自动列并且无法从其他位置获取其大小,则测量系统将中断并可能导致图形损坏.

所以,我想我们可以将这些规则结合成一个总体理念:

如果元素跨越多个列并且这些列中的至少一个(但不是全部)是自动调整大小,则必须存在另一个不跨越的列以提供自动调整大小的列的大小.否则,行为最多是意料之外的,最坏的是腐败.

随意提出微软的一个错误,但由于现在这是网格控件的定义行为,我想我们在WPF的生命周期中坚持使用它.