【问题标题】:Add new row to Datagrid in a UserControl WPF/VB在 UserControl WPF/VB 中向 Datagrid 添加新行
【发布时间】:2012-07-04 15:29:26
【问题描述】:

我正在尝试创建一个由 DataGrid 和几个按钮组成的 UserControl。按钮将处理添加/删除行(需要是按钮)。 DataGrid 绑定到自定义的可观察集合。集合属性会有所不同(所以我会自动生成列)。

如何添加新行?通常我只会修改可观察的集合。我尝试将新行直接添加到控件中:

dgMain.Items.Add(New DataGridRow())

但我收到一个对我来说意义不大的错误:

使用 ItemsSource 时操作无效。改为使用 ItemsControl.ItemsSource 访问和修改元素。

下面是当前代码:

Public Class DataGrid

Sub New()
    InitializeComponent()
End Sub

#Region "Dependency Properties"
Public Shared MyItemsSourceProperty As DependencyProperty = DependencyProperty.Register("MyItemsSource", GetType(IEnumerable), GetType(DataGrid))
Public Property MyItemsSource() As IEnumerable
    Get
        Return DirectCast(GetValue(MyItemsSourceProperty), IEnumerable)
    End Get
    Set(value As IEnumerable)
        SetValue(MyItemsSourceProperty, value)
    End Set
End Property

#End Region

#Region "Buttons"
Private Sub btnAdd_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnAdd.Click
    dgMain.Items.Add(New DataGridRow())
End Sub
#End Region

End Class

那么有人知道如何添加新行吗?

感谢您的帮助。

编辑:这是创建数据的方式:

Dim np As New ObPerson
np.Add(New Person With {.FirstName = "Jane", .LastName = "Mitel", .Age = 18})
np.Add(New Person With {.FirstName = "Joe", .LastName = "Bloggs", .Age = 92})

UserControlInstance.MyItemsSource = np

Public Class ObPerson
    Inherits ObservableCollection(Of Person)
End Class

EDIT2:接受答案的 VB 版本:

Public Shared Sub AddNewElement(l As IList)
    If l Is Nothing OrElse l.Count = 0 Then
        Throw New ArgumentNullException()
    End If
    Dim obj As Object = Activator.CreateInstance(l(0).[GetType]())
    l.Add(obj)
End Sub

Usage: AddNewElement(MyItemsSource)

【问题讨论】:

  • 您是否尝试过将项目直接添加到 ItemsSource(集合)?线索在错误中...您已绑定到 ItemsSource,但网格不支持通过 Items.Add 添加/删除。使用 ItemsSource(或原始集合)。如果您无法获得对原始集合的引用,您可以将 ItemsSource 转换为原始集合类型

标签: wpf vb.net datagrid row add


【解决方案1】:

您需要使用绑定的集合 - 而不是网格上的“项目”属性。 ItemsSource 将指向您绑定的集合:

SomeGrid.ItemsSource = SomeCollection;

SomeCollection.Add(new ItemOfTheRightType());

(SomeGrid.ItemsSource as SomeCollection).Add(new ItemOfTheRightType());

错误提示如果您使用 Grid.ItemsSource 进行绑定,则无法使用 Grid.Items

编辑:

如果您在运行时不知道项目类型(可能是因为这是使用控件等的第 3 方,并且您想要一个通用的 add 方法),您需要在底层接口上调用 .Add 方法。大多数列表类型都继承自 .NET 框架中的 IList

我不是 VB 专家,我更喜欢 c#,所以我会给你 c#。您需要先检查底层类型:

在c#中

if(grid.ItemsSource is IList) 
{
    (grid.ItemsSource as IList).Add(new childType()); <-- other issue here..
}

但您遇到的问题是,如果您要向集合中添加新项目并且您不知道列表类型,则 IList 需要将对象的实例添加到列表中

  • 解决方案是使用反射:

Dynamically creating a new instance of IList's type

一个有趣的迟来的答案是:

var collectionType = targetList.GetType().GetProperty("Item").PropertyType; 
var constructor = collectionType.GetConstructor(Type.EmptyTypes); 
var newInstance = constructor.Invoke(null); 

这可能有效

【讨论】:

  • 您好 Charleh,感谢您的回复并解释错误。我已按照您的建议将 ItemSource 声明从 XAML 移到代码中(Me.dgMain.ItemsSource = MyItemsSource),但集合(MyItemsSource as IEnumerable)没有与之关联的“添加”函数。我错过了什么!?
  • 我并没有说要将声明移出 XAML,一定要把它保留在那里。后面的代码越少越好。您需要强制转换为您的绑定类型 - 绑定到网格的集合类型是 ObservableCollection 其中 x 是项目类型吗?如果是这样,您需要强制转换 - 这将具有 .Add 方法
  • 好的,谢谢。如果我不知道项目类型是什么,我该如何施放?我在原始问题中添加了用户控件的典型用法
  • Charleh,感谢您引导我完成此操作,我现在可以正常工作了!我已经为我的原始问题添加了答案的 VB 版本,以防其他人需要它。非常感谢。
  • 看起来不错 - 但如果列表中没有项目,则无法使用,但如果您不为此烦恼,那么它会很有魅力:)(也可能无法使用如果对象上没有默认构造函数……但那是程序员的问题!)
猜你喜欢
  • 1970-01-01
  • 2016-11-09
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 2018-12-14
  • 2011-06-05
相关资源
最近更新 更多