Search code examples
wpfvb.netdatagridviewcode-behindtelerik-grid

Create table dynamically in WPF (VB.Net)


I want to create an editable table and it size is defined by user (size can be 10*10 or 20*20 or 30*30).

--

I found this topic (here) but it's running in WinForms, and the DataGridView is not supported by WPF.

I tried with a DataGrid, but the following row doesn't working :

Me.DataGridTableau.ItemsSource = dt

--

I tried with a RadGridView (Telerik) but rows are only updatable by ItemsSource property, and like I don't know how many columns will be, I can't create an object which represents the table (x properties for x columns).

Can anybody help me?


Solution

  • If anybody need it, I found a solution using a RadGridView (Telerik) :

    Create this class :

    Imports System.Dynamic
    Imports System.Collections.Generic
    Imports System.ComponentModel
    
    Public Class MyDataRow
        Inherits DynamicObject
        Implements INotifyPropertyChanged
    
        ReadOnly data As IDictionary(Of String, Object)
    
        Public Sub New()
            data = New Dictionary(Of String, Object)()
        End Sub
    
        Public Sub New(ByVal source As IDictionary(Of String, Object))
            data = source
        End Sub
    
        Public Overrides Function GetDynamicMemberNames() As IEnumerable(Of String)
            Return data.Keys
        End Function
    
        Public Overrides Function TryGetMember(ByVal binder As GetMemberBinder, ByRef result As Object) As Boolean
            result = Me(binder.Name)
            Return True
        End Function
    
        Public Overrides Function TrySetMember(ByVal binder As SetMemberBinder, ByVal value As Object) As Boolean
            Me(binder.Name) = value
            Return True
        End Function
    
        Default Public Property Item(ByVal columnName As String) As Object
            Get
                If data.ContainsKey(columnName) Then
                    Return data(columnName)
                End If
    
               Return Nothing
            End Get
    
        Set(ByVal value As Object)
            If Not data.ContainsKey(columnName) Then
                data.Add(columnName, value)
                OnPropertyChanged(columnName)
            Else
                If data(columnName) <> value Then
                    data(columnName) = value
                    OnPropertyChanged(columnName)
                End If
            End If
        End Set
    End Property
    
    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    
    Protected Sub OnPropertyChanged(name As String)
        Try
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
        Catch
            If Debugger.IsAttached Then Debugger.Break()
            Throw ' rethrow exception
        End Try
    End Sub
    Protected Sub OnPropertyChanged(event_args As PropertyChangedEventArgs)
        RaiseEvent PropertyChanged(Me, event_args)
    End Sub
    
    End Class
    

    In your VM, you need a public property :

        Private _tableau As ObservableCollection(Of MyDataRow)
    Public Property Tableau() As ObservableCollection(Of MyDataRow)
        Get
            Return _tableau
        End Get
        Set(ByVal value As ObservableCollection(Of MyDataRow))
            _tableau = value
            OnPropertyChanged("Tableau")
        End Set
    End Property
    

    You need to create a method to load your table :

       Private Function LoadTableau() As ObservableCollection(Of MyDataRow)
        Dim taille As Integer = Me.GetTailleTableau()
        If taille = 0 Then Return Nothing
    
        Dim data As New ObservableCollection(Of MyDataRow)()
    
        For i As Integer = 0 To (taille - 1)
            Dim row = New MyDataRow()
    
            For j As Integer = 0 To (taille - 1)
                'row(String.Format("Column{0}", j)) = String.Format("Cell {0} {1}", i, j)
                row(j) = ""
            Next
    
            data.Add(row)
        Next
    
        Return data
    End Function
    

    You need to load your table :

    Me.Tableau = Me.LoadTableau()
    

    And you need to bind your table :

    <telerik:RadGridView x:Name="RadGridViewTableau" ItemsSource="{Binding Tableau}" >
    

    I hope this help :)