WindowForms - Correct strategy for editing child rows in a datagridview?

WindowForms - Correct strategy for editing child rows in a datagridview?

Old forum URL: forums.lhotka.net/forums/t/11222.aspx


gajit posted on Sunday, March 11, 2012

Hi all,

I'm looking for someone to point me in the right direction on this.

I have a parentedit form that presents childitems in a datagridview - and I'd like the user to be able to edit the child items directly in the datagridview.

I always used to handle this relationship in a separate childedit form - even in my CSLA2 code, but now I have a necessity to do it in the parent form.

my objects are a businessbase and businessbindinglistbase(of businessbase)

Are these the correct sterotypes to inherit from?

I am using Encapsulated Invocation and My class makeup is currently:

UserProfileEdit (BB), (I)IUserProfieDal and

UserPermission (BB), UserPermissions (BBLB), (I)UserPermissionDal

Do I need to implement a UserPermissionEdit class also?

Any advice would be appreciated.

Thanks,

Graham

 

 

 

 

JonnyBee replied on Sunday, March 11, 2012

1. Yes - that is the correct base classes.

2. UserPermissionEdit - depends on the stereotyope of UserPermission.
    Assuming that "UserPermission" is of stereotype EditableChild you are not required to create a new UserPermissionEdit class.

gajit replied on Sunday, March 11, 2012

Hmmm.

I seem to have the pieces in place, but maybe I'm missing something... when I change a value in the datagridview, my BO doesn;t seem to be getting am IsDorty notification....

 

This is my UserPermission class:

Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports Csla
Imports Csla.Serialization

<Serializable()> _
Public Class UserPermission
    Inherits BusinessBase(Of UserPermission)
    Public Shared ReadOnly NameProperty As PropertyInfo(Of String) = RegisterProperty(Of String)(Function(c) c.Name)
    Public Property Name() As String
        Get
            Return GetProperty(NameProperty)
        End Get
        Private Set(value As String)
            LoadProperty(NameProperty, value)
        End Set
    End Property

    Public Shared ReadOnly CreateFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.CreateFlag)
    Public Property CreateFlag() As Boolean
        Get
            Return GetProperty(CreateFlagProperty)
        End Get
        Set(value As Boolean)
            SetProperty(CreateFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly ShowCreateFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.ShowCreateFlag)
    Public Property ShowCreateFlag() As Boolean
        Get
            Return GetProperty(ShowCreateFlagProperty)
        End Get
        Set(value As Boolean)
            LoadProperty(ShowCreateFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly DeleteFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.DeleteFlag)
    Public Property DeleteFlag() As Boolean
        Get
            Return GetProperty(DeleteFlagProperty)
        End Get
        Set(value As Boolean)
            SetProperty(DeleteFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly ShowDeleteFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.ShowDeleteFlag)
    Public Property ShowDeleteFlag() As Boolean
        Get
            Return GetProperty(ShowDeleteFlagProperty)
        End Get
        Set(value As Boolean)
            LoadProperty(ShowDeleteFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly EditFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.EditFlag)
    Public Property EditFlag() As Boolean
        Get
            Return GetProperty(EditFlagProperty)
        End Get
        Set(value As Boolean)
            SetProperty(EditFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly ShowEditFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.ShowEditFlag)
    Public Property ShowEditFlag() As Boolean
        Get
            Return GetProperty(ShowEditFlagProperty)
        End Get
        Set(value As Boolean)
            LoadProperty(ShowEditFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly ViewFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.ViewFlag)
    Public Property ViewFlag() As Boolean
        Get
            Return GetProperty(ViewFlagProperty)
        End Get
        Set(value As Boolean)
            SetProperty(ViewFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly ShowViewFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.ShowViewFlag)
    Public Property ShowViewFlag() As Boolean
        Get
            Return GetProperty(ShowViewFlagProperty)
        End Get
        Set(value As Boolean)
            LoadProperty(ShowViewFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly ExecFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.ExecFlag)
    Public Property ExecFlag() As Boolean
        Get
            Return GetProperty(ExecFlagProperty)
        End Get
        Set(value As Boolean)
            SetProperty(ExecFlagProperty, value)
        End Set
    End Property

    Public Shared ReadOnly ShowExecFlagProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(c) c.ShowExecFlag)
    Public Property ShowExecFlag() As Boolean
        Get
            Return GetProperty(ShowExecFlagProperty)
        End Get
        Set(value As Boolean)
            LoadProperty(ShowExecFlagProperty, value)
        End Set
    End Property

    Friend Shared Function NewUserPermission( _
        _name As String _
        , _createflag As Boolean _
        , _deleteflag As Boolean _
        , _editflag As Boolean _
        , _viewflag As Boolean _
        , _execflag As Boolean _
  ) As UserPermission
        Return New UserPermission( _
             _name _
            , _createflag _
            , _deleteflag _
            , _editflag _
            , _viewflag _
            , _execflag _
              )
    End Function

    Friend Shared Function GetUserPermission( _
            data As Csla.Data.SafeDataReader _
      ) As UserPermission
        Return New UserPermission(data)
    End Function

    Private Sub New()
        MarkAsChild()
    End Sub

    Private Sub New(ByVal data As Csla.Data.SafeDataReader)
        MarkAsChild()
        Child_Fetch(data)
    End Sub

    Private Sub New( _
            _name As String _
            , _createflag As Boolean _
            , _deleteflag As Boolean _
            , _editflag As Boolean _
            , _viewflag As Boolean _
            , _execflag As Boolean _
        )
        MarkAsChild()
        Name = _name
        CreateFlag = _createflag
        DeleteFlag = _createflag
        EditFlag = _editflag
        ViewFlag = _viewflag
        ExecFlag = _execflag

    End Sub

#If SILVERLIGHT Then
  <System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> _
  Public Overrides Sub Child_Create()
   Using BypassPropertyChecks
   End Using
   MyBase.Child_Create()
  End Sub
#Else
    Protected Overrides Sub Child_Create()
        Using BypassPropertyChecks
        End Using
        MyBase.Child_Create()
    End Sub

    Private Sub Child_Fetch(data As Csla.Data.SafeDataReader)
        Using BypassPropertyChecks
            Name = data.GetString(data.GetOrdinal("NAME"))

            CreateFlag = IIf(data.GetInt32(data.GetOrdinal("CREATEFLAG")) = 1, True, False)
            ShowCreateFlag = IIf(data.GetInt32(data.GetOrdinal("SHOWCREATEFLAG")) = 1, True, False)
            DeleteFlag = IIf(data.GetInt32(data.GetOrdinal("DELETEFLAG")) = 1, True, False)
            ShowDeleteFlag = IIf(data.GetInt32(data.GetOrdinal("SHOWDELETEFLAG")) = 1, True, False)
            EditFlag = IIf(data.GetInt32(data.GetOrdinal("EDITFLAG")) = 1, True, False)
            ShowEditFlag = IIf(data.GetInt32(data.GetOrdinal("SHOWEDITFLAG")) = 1, True, False)
            ViewFlag = IIf(data.GetInt32(data.GetOrdinal("VIEWFLAG")) = 1, True, False)
            ShowViewFlag = IIf(data.GetInt32(data.GetOrdinal("SHOWVIEWFLAG")) = 1, True, False)
            ExecFlag = IIf(data.GetInt32(data.GetOrdinal("EXECFLAG")) = 1, True, False)
            ShowExecFlag = IIf(data.GetInt32(data.GetOrdinal("SHOWEXECFLAG")) = 1, True, False)

        End Using
    End Sub

    Private Sub Child_Update(_userprofileedit As UserProfileEdit)
        Using BypassPropertyChecks
            Using dalManager = ParabolaSols.DataAccess.SecurityDalFactory.GetManager()
                Dim dal = dalManager.GetProvider(Of ParabolaSols.DataAccess.IUserPermissionDal)()
                Using BypassPropertyChecks
                    dal.Update( _
                                            _userprofileedit.Username _
                                            , Name _
                                            , CreateFlag _
                                            , DeleteFlag _
                                            , EditFlag _
                                            , ViewFlag _
                                            , ExecFlag _
                            )
                End Using
                FieldManager.UpdateChildren(Me)
            End Using
        End Using
    End Sub

#End If
End Class


Am I maybe missing something? What aspect of the framework marks the parent as dirty when a child is changed? I vaguely remember in CSLA2 having to raise a ListChanged event when a child was changed...

Thanks,

G.

tiago replied on Sunday, March 11, 2012

Hi Graham,

I presume the use case goes like this:

1) I have a user profile form (Editable Root) that has a collection of user permissions for different areas of the application

So far so good. Now there are several possibilities:

2-A) The collection of user permissions is on a DataGridView that is saved at the same time the user profile is saved (collection of user permissions is an Editable Child List)

2-B) The collection of user permissions is on an independent DataGridView that is saved on its own and NOT when we save the user profile (collection of user permissions is an Editable Root List)

2-C) The collection of user permissions is on an independent DataGridView and each permission it saved as soon as we move to another line of the grid (collection of user permissions is an Dynamic Root List)

Is the DataGridView part of the user profile form? If the answer is yes:

Using 2-A seems the best option as there is only Save (and Cancel) button that saves (or cancels) everything you see it on the form.

A final comment to say that although misleading, option 2-C is used quite commonly.

gajit replied on Sunday, March 11, 2012

Thanks Tiago.

Yes, your use case analysis is correct, and 2A is my preferred method - as that maintains the look and feel I have previously adopted in CSLA dev.

I believe I have the correct business classes in place, just a matter of figuring out why my child changes arent being passed up to my parent BO as changed.

I did look at the 2B/2C method briefly, which I still _could_ use, But to maintain consistency with what I currently do, i'd have to just check the status of both parent BO's in the form and call save on those when Isdirty is present.... but I think 2A's still the way to go .. for me at least.

Thanks,

Graham

 

gajit replied on Sunday, March 11, 2012

I have confirmed that the child update DOES cascade updates correctly.

My only issue now is that the changes made to my child are not reflected on the form - i.e. my parent BO is not being marked as IsDirty - I have to change something on the parent record in order to force the IsDirty....

Any ideas why?

Thanks,

Graham

 

JonnyBee replied on Sunday, March 11, 2012

Your property Set should always use SetProperty and not LoadProperty.

LoadProperty is intended for DAL code and will not make property/object dirty whereas SetProperty will enforce authorization rules and make property Dirty and run rules when property value is changed. and raise OnPropertyChanged to notify UI.  

How is the Child list property declared in UserProfileEdit?

gajit replied on Sunday, March 11, 2012

Actually Jonny,

The LoadProperty methods are impkemented for the fields that don't require updates - for each of the "xxxFlag" properites I load, there is a matching "ShowxxxxFlag" Property which just tells the UI whether I display the control (checkbox) in the client.

I made some changes to my UserprofileEdit = specifically adding the OnChildChanged and was about to send the relevant pieces of code to you, then found the issue...

    Protected Overrides Sub OnChildChanged(e As Csla.Core.ChildChangedEventArgs)
        If TypeOf e.ChildObject Is UserPermission Then '*****I was checking the UserPermissions collection and not the BB object - Duh!
            BusinessRules.CheckRules(UserPermissionsProperty
            OnPropertyChanged(UserPermissionsProperty)
        End If
        If TypeOf e.ChildObject Is UserRole Then
            BusinessRules.CheckRules(UserRolesProperty)
            OnPropertyChanged(UserRolesProperty)
        End If
        MyBase.OnChildChanged(e)
    End Sub

Thanks again!

This stuff is starting to Rock!

Graham

 

Copyright (c) Marimer LLC