这个问题可能有点开放,但我正在寻找有关如何动态合并和分割网格单元的问题的建议。
所以目前我生成一个X行和Y列的网格,然后用StackPanel填充每个单元格。单击时,StackPanel会添加一个边框,并且会修改一个表示每个网格单元格的bool值的数组,以显示它已被单击。网格没有其他控件。这些都是在c#中以编程方式完成的,而不是在xaml中完成的。
我想要做的是通过点击按钮合并并拆分网格中的所选单元格(如果它们彼此相邻)。我发现没有办法轻易做到这一点,我想知道是否有人可以为这个问题推荐一个好方法。
我不依赖于我目前的方法,并且赞赏任何其他方法建议。
答案 0 :(得分:2)
我刚刚在Github上发布了一个如何执行此操作的示例。
基本思想是使用最大行数和列数初始化网格,然后创建和删除单元格,同时根据需要修改其位置和跨度以填充网格。
以下是最相关的摘录:
public MainWindow()
{
InitializeComponent();
var numRows = grid.RowDefinitions.Count;
var numCols = grid.ColumnDefinitions.Count;
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < numCols; j++)
{
var item = new DynamicGridItem(j, i);
item.Merge += HandleMerge;
item.Split += HandleSplit;
grid.Children.Add(item);
Grid.SetRow(item, i);
Grid.SetColumn(item, j);
}
}
}
在这里,您可以看到我的单元格项是一个自定义UserControl
类,其构造函数将两个整数作为X和Y网格坐标。然后可以使用这些坐标来简化网格行和列分配。在我的示例中,它们并不是绝对必要的,但如果存储/加载网格项并在其他代码模块中使用它们可能会有所帮助。
我的示例使用带有布尔事件参数的单个Merge
事件来指示合并是向左还是向右。实际的事件处理程序只是确定是向左还是向右偏移,并将该信息以及源项传递给下面的HandleMergeOffset
方法。
private void HandleMergeOffset(DynamicGridItem item, int offset)
{
var otherItem = FindItemByXOffset(item, offset);
if (otherItem == null)
{
return; // Nothing to do
}
otherItem.Merge -= HandleMerge;
otherItem.Split -= HandleSplit;
Grid.SetColumnSpan(item, Grid.GetColumnSpan(item) + Grid.GetColumnSpan(otherItem));
grid.Children.Remove(otherItem);
if (offset < 0) // Reposition item if merging left
{
Grid.SetColumn(item, otherItem.X);
item.X = otherItem.X;
}
}
你可能写一个比我更好的FindItem
方法。基本思路是找到要删除的邻居,展开当前项目以包括原始列跨度,从已删除项目中取消挂钩事件,当然还要从网格中删除它。
由于我们删除了Merge
上的某个项目,因此我们会在Split
上创建一个新项目。我决定不打扰SplitLeft
或SplitRight
指定。此代码将始终在原始单元格的最左侧索引处创建最小单元格,并将其余部分向右推。
private void HandleSplit(object sender, EventArgs e)
{
var item = (DynamicGridItem)sender;
var itemColSpan = Grid.GetColumnSpan(item);
if (itemColSpan < 2)
{
return; // Nothing to do
}
var newItem = new DynamicGridItem(item.X, item.Y);
newItem.Merge += HandleMerge;
newItem.Split += HandleSplit;
grid.Children.Add(newItem);
Grid.SetColumn(newItem, newItem.X);
Grid.SetRow(newItem, newItem.Y);
Grid.SetColumn(item, item.X + 1);
Grid.SetColumnSpan(item, itemColSpan - 1);
item.X += 1;
}
请注意,这不会尝试将单个单元格拆分为半个单元格(这样我们就不会改变原始网格或处理子网格)。如果您需要任意动态网格行为,您将想要寻找其他地方。