uniformgrid实现跨越

发布于:2025-07-10 ⋅ 阅读:(17) ⋅ 点赞:(0)

以下是 **自定义 `SpanningUniformGrid` 的完整实现**(无需 NuGet 依赖),支持跨行(`RowSpan`)和跨列(`ColumnSpan`),同时保持 `UniformGrid` 的均等分布特性:

 

---

 

### **1. 定义 `SpanningUniformGrid` 类**

```csharp

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

 

public class SpanningUniformGrid : UniformGrid

{

    // 注册附加属性:RowSpan

    public static readonly DependencyProperty RowSpanProperty =

        DependencyProperty.RegisterAttached(

            "RowSpan",

            typeof(int),

            typeof(SpanningUniformGrid),

            new PropertyMetadata(1));

 

    public static int GetRowSpan(DependencyObject obj) => 

        (int)obj.GetValue(RowSpanProperty);

    public static void SetRowSpan(DependencyObject obj, int value) => 

        obj.SetValue(RowSpanProperty, value);

 

    // 注册附加属性:ColumnSpan

    public static readonly DependencyProperty ColumnSpanProperty =

        DependencyProperty.RegisterAttached(

            "ColumnSpan",

            typeof(int),

            typeof(SpanningUniformGrid),

            new PropertyMetadata(1));

 

    public static int GetColumnSpan(DependencyObject obj) => 

        (int)obj.GetValue(ColumnSpanProperty);

    public static void SetColumnSpan(DependencyObject obj, int value) => 

        obj.SetValue(ColumnSpanProperty, value);

 

    // 重写布局逻辑

    protected override Size ArrangeOverride(Size finalSize)

    {

        if (Children.Count == 0)

            return finalSize;

 

        // 计算每个单元格的宽度和高度

        double cellWidth = finalSize.Width / Columns;

        double cellHeight = finalSize.Height / Rows;

 

        foreach (UIElement child in Children)

        {

            if (child == null)

                continue;

 

            // 获取子元素的位置和跨度

            int row = GetRow(child);

            int column = GetColumn(child);

            int rowSpan = Math.Max(1, GetRowSpan(child));

            int columnSpan = Math.Max(1, GetColumnSpan(child));

 

            // 计算子元素的布局矩形

            Rect rect = new Rect(

                column * cellWidth,

                row * cellHeight,

                columnSpan * cellWidth,

                rowSpan * cellHeight);

 

            // 应用布局

            child.Arrange(rect);

        }

 

        return finalSize;

    }

}

```

 

---

 

### **2. 在 XAML 中使用**

```xml

<Window xmlns:local="clr-namespace:YourNamespace">

    <local:SpanningUniformGrid Rows="2" Columns="3">

        <!-- 跨2列 -->

        <Button 

            Content="跨2列" 

            local:SpanningUniformGrid.ColumnSpan="2" 

            Background="LightBlue"/>

 

        <!-- 跨2行 -->

        <Button 

            Content="跨2行" 

            local:SpanningUniformGrid.RowSpan="2" 

            Grid.Row="0" Grid.Column="2"

            Background="LightGreen"/>

 

        <!-- 普通单元格 -->

        <Button Content="A" Grid.Row="1" Grid.Column="0"/>

        <Button Content="B" Grid.Row="1" Grid.Column="1"/>

    </local:SpanningUniformGrid>

</Window>

```

 

---

 

### **3. 效果展示**

布局结果如下(类似 HTML 表格的 `colspan`/`rowspan`):

```

[ 跨2列 (占2列) ][ 跨2行 (占2行) ]

[ A ][ B ] [ 跨2行延续 ]

```

 

---

 

### **4. 关键点说明**

1. **附加属性**:  

   - 通过 `RowSpan` 和 `ColumnSpan` 控制子元素的跨度。

   - 默认值为 `1`(不跨越)。

 

2. **布局逻辑**:  

   - 计算每个单元格的固定大小(`cellWidth`/`cellHeight`)。

   - 根据跨度和位置分配子元素的实际区域。

 

3. **兼容性**:  

   - 保留 `UniformGrid` 的所有原生功能(如 `Rows`/`Columns` 属性)。

   - 支持与 `Grid.Row`/`Grid.Column` 共存。

 

---

 

### **5. 性能优化建议**

- **静态布局**:如果子元素位置固定,可在加载后调用 `UpdateLayout()` 冻结布局。

- **虚拟化**:对大量动态项,建议结合 `VirtualizingPanel`。

 

---

 

### **6. 对比现成方案**

| 特性 | 自定义 `SpanningUniformGrid` | NuGet 包(如 `EnhancedUniformGrid`) |

|--------------------|-----------------------------|--------------------------------------|

| **跨行/跨列** | ✅ | ✅ |

| **代码量** | 需手动实现(约 50 行) | 直接安装,零代码 |

| **维护性** | 需自行维护 | 依赖第三方更新 |

| **适用场景** | 拒绝 NuGet 的严格环境 | 快速开发 |

 

---

 

### **总结**

- **推荐场景**:  

  - 企业内部分享控件库。  

  - 对 NuGet 引入限制严格的项目。  

- **备用方案**:  

  - 直接使用 `Grid`(原生支持跨单元格,但需手动定义行列)。  

  - 安装 `EnhancedUniformGrid` 包(省时省力)。  

 

如果需要进一步扩展(如动态跨度计算),可以重写 `MeasureOverride` 方法优化测量逻辑。


网站公告

今日签到

点亮在社区的每一天
去签到