我正在创建一个继承自 WPF DataGrid 的控件 (CustomGrid)。 无论何时使用 CustomGrid,它都会将 ItemsSource 设置为一个 Observable Collection。 我要添加的功能之一是能够从剪贴板粘贴数据,但是如果集合中当前没有足够的行,那么我想添加额外的行。 这就是我被困的地方。 CustomGrid 将用于不同的集合,因此我无法引用集合所基于的类。 使用 ItemsSource,如何添加额外的行。
这是我到目前为止尝试过的...
private void AddNewRow()
{
IList itemsSource = this.ItemsSource as IList;
Type itemType = itemsSource.GetType().GenericTypeArguments[0];
object newRecord = Activator.CreateInstance(itemType);
itemsSource.Add(newRecord);
}
Error: System.IndexOutOfRangeException: 'Index was outside of the bounds of the array.'
知道我可能做错了什么吗?
我建议您创建一个生成 RowDefinition(和 ColumnDefinition)的 Helper:
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
namespace Helpers
{
public class GridHelpers
{
#region RowCount Property
/// <summary>
/// Adds the specified number of Rows to RowDefinitions.
/// Default Height is Auto
/// </summary>
public static readonly DependencyProperty RowCountProperty =
DependencyProperty.RegisterAttached(
"RowCount", typeof(int), typeof(GridHelpers),
new PropertyMetadata(-1, RowCountChanged));
// Get
public static int GetRowCount(DependencyObject obj)
{
return (int)obj.GetValue(RowCountProperty);
}
// Set
public static void SetRowCount(DependencyObject obj, int value)
{
obj.SetValue(RowCountProperty, value);
}
// Change Event - Adds the Rows
public static void RowCountChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || (int)e.NewValue < 0)
return;
Grid grid = (Grid)obj;
grid.RowDefinitions.Clear();
for (int i = 0; i < (int)e.NewValue; i++)
grid.RowDefinitions.Add(
new RowDefinition() { Height = GridLength.Auto });
SetPixelOrStarRows(grid);
}
#endregion
#region ColumnCount Property
/// <summary>
/// Adds the specified number of Columns to ColumnDefinitions.
/// Default Width is Auto
/// </summary>
public static readonly DependencyProperty ColumnCountProperty =
DependencyProperty.RegisterAttached(
"ColumnCount", typeof(int), typeof(GridHelpers),
new PropertyMetadata(-1, ColumnCountChanged));
// Get
public static int GetColumnCount(DependencyObject obj)
{
return (int)obj.GetValue(ColumnCountProperty);
}
// Set
public static void SetColumnCount(DependencyObject obj, int value)
{
obj.SetValue(ColumnCountProperty, value);
}
// Change Event - Add the Columns
public static void ColumnCountChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || (int)e.NewValue < 0)
return;
Grid grid = (Grid)obj;
grid.ColumnDefinitions.Clear();
for (int i = 0; i < (int)e.NewValue; i++)
grid.ColumnDefinitions.Add(
new ColumnDefinition() { Width = GridLength.Auto });
SetPixelOrStarColumns(grid);
}
#endregion
#region StarRows Property
/// <summary>
/// Makes the specified Row's Height equal to Star.
/// Can set on multiple Rows
/// </summary>
public static readonly DependencyProperty StarRowsProperty =
DependencyProperty.RegisterAttached(
"StarRows", typeof(string), typeof(GridHelpers),
new PropertyMetadata(string.Empty, StarRowsChanged));
// Get
public static string GetStarRows(DependencyObject obj)
{
return (string)obj.GetValue(StarRowsProperty);
}
// Set
public static void SetStarRows(DependencyObject obj, string value)
{
obj.SetValue(StarRowsProperty, value);
}
// Change Event - Makes specified Row's Height equal to Star
public static void StarRowsChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || string.IsNullOrEmpty(e.NewValue.ToString()))
return;
SetStarRows((Grid)obj);
}
#endregion
#region StarColumns Property
/// <summary>
/// Makes the specified Column's Width equal to Star.
/// Can set on multiple Columns
/// </summary>
public static readonly DependencyProperty StarColumnsProperty =
DependencyProperty.RegisterAttached(
"StarColumns", typeof(string), typeof(GridHelpers),
new PropertyMetadata(string.Empty, StarColumnsChanged));
// Get
public static string GetStarColumns(DependencyObject obj)
{
return (string)obj.GetValue(StarColumnsProperty);
}
// Set
public static void SetStarColumns(DependencyObject obj, string value)
{
obj.SetValue(StarColumnsProperty, value);
}
// Change Event - Makes specified Column's Width equal to Star
public static void StarColumnsChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || string.IsNullOrEmpty(e.NewValue.ToString()))
return;
SetStarColumns((Grid)obj);
}
#endregion
private static void SetStarColumns(Grid grid, GridUnitType type = GridUnitType.Star)
{
//another way using Regex.Split
//var starColumns = Regex.Split(GetStarColumns(grid), @",(?![^()]*\))")
// .Where(x => !string.IsNullOrEmpty(x))
// .Select(m =>
// {
// var v = Regex.Replace(m, @"[\(\) ]", "");
// return (v.Contains(",") ? v : $"{v},1").Split(',')
// .Select(int.Parse)
// .ToArray();
// })
// .ToDictionary(x => x[0], x => x[1]);
var regex = new Regex(@"(?:(?:\((?>[^()]+|\((?<number>)|\)(?<-number>))*(?(number)(?!))\))|[^,])+");
var starColumns = regex.Matches(GetStarColumns(grid))
.Cast<Match>()
.Select(m =>
{
var v = Regex.Replace(m.Value, @"[\(\) ]", "");
return (v.Contains(",") ? v : $"{v},1").Split(',')
.Select(int.Parse)
.ToArray();
})
.ToDictionary(x => x[0], x => x[1]);
if (starColumns.Count == 0) return;
for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
{
if(starColumns.TryGetValue(i, out int nbrStar))
grid.ColumnDefinitions[i].Width =
new GridLength(nbrStar, type);
}
}
private static void SetStarRows(Grid grid, GridUnitType type = GridUnitType.Star)
{
var regex = new Regex(@"(?:(?:\((?>[^()]+|\((?<number>)|\)(?<-number>))*(?(number)(?!))\))|[^,])+");
var starRows = regex.Matches(GetStarRows(grid))
.Cast<Match>()
.Select(m =>
{
var v = Regex.Replace(m.Value, @"[\(\) ]", "");
return (v.Contains(",") ? v : $"{v},1").Split(',')
.Select(int.Parse)
.ToArray();
})
.ToDictionary(x => x[0], x => x[1]);
for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
{
if (starRows.TryGetValue(i, out int nbrStar))
grid.RowDefinitions[i].Height =
new GridLength(nbrStar, GridUnitType.Star);
}
}
}
}
使用方法:
xmlns:local="clr-namespace:Helpers"
:
<Grid
local:GridHelpers.RowCount="3"
local:GridHelpers.ColumnCount="3"
local:GridHelpers.StarRows="(2,10)"
local:GridHelpers.StarColumns="0,(1,3),(2,2)">
相当于 :
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
重新定义的好处是你可以绑定你想要的东西
local:GridHelpers.RowCount="{Binding RowCount}"
等等....
代码通俗易懂...