如何在不知道它绑定到哪个集合的情况下向 DataGrid 添加行

问题描述 投票:0回答:1

我正在创建一个继承自 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.'

知道我可能做错了什么吗?

c# wpf datagrid itemssource activator
1个回答
0
投票

我建议您创建一个生成 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}"

等等....

代码通俗易懂...

© www.soinside.com 2019 - 2024. All rights reserved.