BrokenRules Sample for root and children like Visual Studio

BrokenRules Sample for root and children like Visual Studio

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


JohnB posted on Monday, March 03, 2008

You can take this sample app and do with it what you want. This is my way of giving something back to the group.

Disclaimer: There are many ways to do what I did. It is certainly not meant to be perfect but just one of many ways to 'skin the cat'.

Application Structure: Csla 3.0.3, VS2005, no database required. I spiced it up a little using the WeifenLuo panels. You should only need to update your Csla reference path.

BrokenRulesSample Application
1) MainForm - The main form for the application and also the container for the message panel what we will use to display broken rules to the user.
2) MessagePanel - Used to display broken rules to the user as they occur with changes made to the data.
3) ContentEdit - Where all the data editing takes place. All user interaction.
4) BaseForm - All ContentEdit forms would inherit from the base form. The reason I did this was so that I could 'hide' the broken rules plumbing from the developer. Nothing gets missed this way...
5) BrokenRulesCollectionHelper - Used to retrieve the broken rules collections from the Csla objects. Read the docs inside the file for more information and many props to Andrés (Xal on the forum) for his work here.

SampleLib
1) SubClassClsa - Again, nothing more than the standard subclassing of Csla with the addition of a few files.
MyBrokenRulesCollection - Esentially a subclass of the Csla BrokenRulesCollection class. Again, read the notes inside the file for more details.

MyBrokenRule - Subclass of Csla BrokenRule.

BrokenRulesChangedEventArgs - Used for custom event to pass around broken rules collection for refreshing or initing.

2) Customer (BB), Addresses (BLB), Address (BB). Standard Csla business objects. Nothing fancy, no database required.

3) CslaTypeHelper - Again, many thanks to Andrés for his work.

Hopefully this little project will help someone out as much as the help I have received here. I figure this is the least that I can do given how much Rocky has given us.

Please feel free to ask any questions, comments, likes, dislikes, bugs I have missed or whatever! I take criticism well!

John

JohnB replied on Tuesday, March 04, 2008

Someone let me know that I forgot to include the assembly for the panels. I did a build and uploaded again. Total download is 4meg.

John

JoeFallon1 replied on Wednesday, March 05, 2008

John,

I just downloaded it and ran through it quickly.

1. Very nice job.

2. Good of you to give Andres credit so prominently in the code.

It was not immediately clear that the buttons in the panel were clickable filters that allow you to see only those errors that apply to the ones that are selected. It is a nice touch though.

In VS 2005 I could not open the ContentEdit.vb [Design] file. I cannot see the form where you lay out all the controls. I get this error:

One or more errors encountered while loading the designer. The errors are listed below. Some errors can be fixed by rebuilding your project, while others may require code changes.

Error HRESULT E_FAIL has been returned from a call to a COM component.

 
If I close the Message Panel there is no way to re-open it.
 
In Public Module BrokenRulesCollectionHelper

Private Sub LoadPropertyData(ByVal objectType As Type)

The code loops until pCurrentType Is Nothing
 
The test inside the loop is for IsBusinessBase. It seems that the loop should stop once IsBusinessBase is True. I thought it continued working its way up the inheritance chain past BusinessBase. (I only looked once and could be mistaken though.)
 
 
Joe
 
 
 

JohnB replied on Wednesday, March 05, 2008

JoeFallon1:
In VS 2005 I could not open the ContentEdit.vb [Design] file. I cannot see the form where you lay out all the controls.
Try rebuilding the project. That should fix your issues. There is nothing special in the form.

JoeFallon1:
If I close the Message Panel there is no way to re-open it.
You need to restart the application. My intention was that this was a demo and I did not bother to wire that part up. I can added it though.

JoeFallon1:
The test inside the loop is for IsBusinessBase. It seems that the loop should stop once IsBusinessBase is True.
It will continue. Notice the recursive call to the InitializeBrokenRules method again.

For Each pMethodInfo As MethodInfo In _propertyData.Item(pType)
    Dim pChildObjectInfo As Object
    pChildObjectInfo = pMethodInfo.Invoke(businessObject, Nothing)

    If pChildObjectInfo Is Nothing Then Exit For

    InitializeBrokenRules(editForm, pChildObjectInfo, False)
Next


Other than that, thanks! I hope others find it useful.

JohnB replied on Friday, March 07, 2008

Just wanted to provide an update. I modified the project to also include grandchild objects. Check it out from the link on the first post.

Thanks,
John

alef replied on Friday, March 07, 2008

 

On the codeplex site they have created something similar. It is called ErrorTreeView.

There is not much explanation of it, but they have created a nice example.

You can download it from:

http://www.codeplex.com/CSLAcontrib/SourceControl/ListDownloadableCommits.aspx

You have to extract the file because there is more in it.

They have created a treeview. So in the treeview you see a visual representation of root, children and grandchildren. By clicking on the error you arrive at the control where you can fix the problem.

 

JohnB replied on Friday, March 07, 2008

Alef,

Thanks for the information. I actually used some of the code from Xal's project, so now we have two examples of how to do this.

The more examples we have the better it is for the community.

John

JohnB replied on Monday, March 10, 2008

Just curious if anyone had any other examples or comments to share about this topic?

Thanks

xal replied on Monday, March 10, 2008

Hey John!
It looks great!! I'm glad you could reuse some of my code.

It's been a while since I've been around the forum, as you may realize. But I'm trying to catch up. I've been quite busy (and still am).

Again: great work!

Andrés

snakebyteme replied on Wednesday, February 03, 2010

Here is a simpler approach that will not recurse forever if you have grandchildren that are the same type as the Parent:

Imports Csla
Imports System.Reflection
Imports System.ComponentModel
Imports System.Text

Public Class BrokenRulesExtractor

  Private mBrokenRules As List(Of Csla.Validation.BrokenRule)

  Public ReadOnly Property BrokenRulesCollection() As List(Of Csla.Validation.BrokenRule)
    Get
      Return mBrokenRules
    End Get
  End Property

  Public Sub GetBrokenRules(ByVal target As Object)
    Dim inspectedObjects As New Collections.Generic.List(Of String)
    mBrokenRules = New List(Of Csla.Validation.BrokenRule)
    GetBrokenRules(target, inspectedObjects)
  End Sub

  Private Sub GetBrokenRules(ByVal target As Object, ByVal inspectedObjects As Collections.Generic.List(Of String))
    Dim returnValue As New StringBuilder
    Dim targetID As String = String.Empty
    If target IsNot Nothing Then
      targetID = target.GetType.ToString & ":" & target.GetHashCode().ToString
    End If
    If target IsNot Nothing AndAlso Not inspectedObjects.Contains(targetID) Then
      inspectedObjects.Add(targetID)
      Dim myType As Type = target.GetType
      If myType.BaseType.Name.Contains("BusinessListBase") Then
        If target.IsDirty Then
          ' check error messages for each row in the list
          For oneItem As Integer = 0 To CType(target, IBindingList).Count - 1
            If TypeOf CType(target, IBindingList)(oneItem) Is Csla.Core.BusinessBase Then
              GetBrokenRules(CType(target, IBindingList)(oneItem), inspectedObjects)
            End If
          Next
        End If
      Else
        If TypeOf target Is Csla.Core.BusinessBase Then
          If target.IsDirty Then
            ' run through broken rules collection for this object
            For Each oneBrokenRule As Csla.Validation.BrokenRule In CType(target, Csla.Core.BusinessBase).BrokenRulesCollection
              ' if we do not have this message already, add it
              If Not mBrokenRules.Contains(oneBrokenRule) Then
                mBrokenRules.Add(oneBrokenRule)
              End If
            Next
            ' get list of properties for this object
            Dim properties() As System.Reflection.PropertyInfo = target.GetType.GetProperties()
            For Each oneProperty As System.Reflection.PropertyInfo In properties
              ' get object that sits on this property
              If Not oneProperty.PropertyType.IsPrimitive AndAlso oneProperty.GetIndexParameters().Length = 0 Then
                Dim propTarget As Object = oneProperty.GetValue(target, Nothing)
                ' call this procedure resursively to get error for property based object
                GetBrokenRules(propTarget, inspectedObjects)
                ' if we do not have this message already, add it
              End If
            Next
          End If
        End If
      End If
    End If

  End Sub

End Class

Copyright (c) Marimer LLC