All entries for September 2005

September 25, 2005

Happy Birthday to ME!

Ah, 21! That is a big number!

September 20, 2005

Standard User

I re-installed XP today and decided to try out running as a standard user, not as an administrator. (I did only switch once I got Office and Visual Studio installed.)

When I do need to be admin, I use this tool: link This prompts for the Administrator password, then mine, which adds me to the Administrators group for the context of a command prompt. Anything I run from that prompt runs with my increased privileges.

I'm going to give it a week or so and see how I get on.


September 17, 2005

My Party

I'm having my 21st birthday party on Friday 23rd September at my house in Leamington. Everyone is welcome. Give me a shout if you don't know where I am.

I know that no one back in Cornwall reads my blog. I just wanted to say "thank you" to you all for replying to the invite I sent via text message… yeah… whatever guys…. see you at Christmas… or not.


WinForms Error Binding

I created a component that handles the boring job of hooking up an object that implements IDataErrorInfo to an ErrorProvider on a form. The data bound object has to implement my IRuleTrigger interface by having two events RuleInvalidated and RuleValidated. These events are listened to by my RuleBinder component. It then enumerates the controls on the form looking for data bindings relevant to the data object. ErrorProvider.SetError is invoked to either set or clear the error on controls as needed.
So now the business object is in control of business rules and the RuleRinder takes care of setting the relevant UI. Thus eliminating all those TextBox.Validated event handlers.
If I get the code commented up properly (when I'm less busy) I'll post it online. It looks like I'm building up a fair amount of code here for a rather nice "Data Binding Framework" library.

September 09, 2005

Document–View Architecture

A current job I'm doing has exposed the need for a half-decent document-view architecture in .NET. Back in my (brief) MFC days it was all about CDocument and CView objects! However in .NET (even 2.0) we are without any infrastructure to build on.

The only proper documented attempt I found online was Chris Sells series Creating Document-Centric Applications in Windows Forms Although Chris does give a rather excellent explanation and full implementation there were a few reasons why I can't use it. First off the "document" aspect is an actual Component, that's great for drag-n-drop style development, but I already have a code base that I simply wish to "act-as" a document. Also Chris's code is a bit too complete, in such a way that it limits my options in terms of implementation of my application. Finally, Chris's code does not easily support multiple document types or multiple views of a single document. All that said, I still thank Chris for that excellent series of articles that certainly got me thinking!

So what is my approach then?

  • Interfaces – Loose Coupling – Flexibilty*
    My framework revolves around 4 simple interfaces:
  • IDocument
  • IDocumentFactory
  • IView
  • IDocumentViewManager

IDocument defines what a document object should be able to do:

Public Interface IDocument
ReadOnly Property IsDirty() As Boolean
ReadOnly Property IsNew() As Boolean
Function Save() As IDocument
Function SaveAs(ByVal context As Object) As IDocument
End Interface
  • Track if it is dirty (has un-saved changes) and if it is new (never saved).
  • Save itself and save it self to a given context. Note that context will usually be a filename, but there is no reason that a certain document type wouldn't save to a database or other location.
Public Interface IView
Property Document() As IDocument
Sub EndEdit()
Event Closing As EventHandler(Of System.ComponentModel.CancelEventArgs)
Event Closed As EventHandler
End Interface
A view should provide some manner of interaction with a document. Typically, this will be a Form or UserControl.
It needs a reference to its document object.
The EndEdit() method will called when saving to allow the view to commit any pending edits to the document.
The Closing event will be listened to by the infrastructure to know when a view has been closed. When the last view of a document it is closing it can ask the user to save changes, etc.
Originally I did not have a Closed event and put the code to remove a document from the application in the Closing handler. However, due to way in which .NET MDI Parent forms raise Closing on all child forms, then raise all the Closed, instead of Closing followed by Closed for each child, I had to require the this additional event. Despite the added implementation detail, it does make more sense in some ways,
Public Interface IDocumentFactory
Function NewDocument() As IDocument
Function OpenDocument(ByVal context As Object) As IDocument
Function CreateView(ByVal document As IDocument) As IView
End Interface

The purpose of a document factory is to allow the framework to open new and existing documents, and to create a view of a document. You wonder why we don’t just create document objects ourselves, but the reason for this interface will become clearer once we delve into the document-view manager class. By abstracting the idea of a document factory we can do clever things like put a factory class into a DLL separate from the document. We can enumerate these factory assemblies without having to load all the associated business logic and document code into our working set. When an application supports a large number of different document types this reduction in memory allocation will certain improve start-up times. Additional meta-data can be added to the factory implementations to describe the documents they can create. This meta-data could be used to build runtime UI, such as “New Document” and “Open Document” dialog boxes.
A factory implementation could even return different document types and views depending on some value passed into the constructor, for example. This would not be possible if the creation logic was in the actual document.

The following interface is the real core of the framework. So it is a little big, but bear with me!

Public Interface IDocumentViewManager
Event ActiveViewChanged As EventHandler
Event ViewListChanged As EventHandler(Of ViewListChangedEventArgs)
Event PromptToSaveChanges As EventHandler(Of PromptToSaveChangesEventArgs)
Event ShowSaveAsUI As EventHandler(Of ShowSaveAsUIEventArgs)

Property ActiveView() As IView
ReadOnly Property Documents() As ReadOnlyCollection(Of IDocument)
ReadOnly Property Views(ByVal document As IDocument) As ReadOnlyCollection(Of IView)
Function NewDocument(ByVal documentFactory As IDocumentFactory) As IDocument
Function OpenDocument(ByVal documentFactory As IDocumentFactory, ByVal context As Object) As IDocument
Function SaveDocument(ByVal document As IDocument) As IDocument
Function SaveDocumentAs(ByVal document As IDocument) As IDocument
Sub CreateView(ByVal document As IDocument, ByVal info As IDocumentFactory)
Sub AddView(ByVal document As IDocument, ByVal view As IView)
End Interface

Before diving into the member-by-member descriptions, I should discuss the overall objective a document-view manager. UIs change and get re-done over time, so it is important to remove the document-view management from any actual UI code. Yes, we could stuff a document list into a MDI form, but that will never be a maintainable solution over time. At the same time I did not want to totally prevent that option. My framework includes an implementation of IDocumentViewManager, but there is nothing to stop someone making a form implement it directly.

A document-view manager basically has a list of documents currently loaded and a list of open views for each document. If provides a central location to create new documents, open existing ones and save them. It can create the default view for a document and also allows a view created externally to be added to a document.
The manager also keeps track of views being closed so it can prompt to save changes if a document is dirty.

First the events:

  • ActiveViewChanged should be raised when, as expected, the active IView in the application has changed. This will allow other UI to update accordingly.
  • ViewListChanged should be raised when an IView is added/deleted to/from a document.
  • PromptToSaveChanges should ask the user if they want to save changes to a given document. The event arguments contain both the document and a “response” property in which to store the selected action (Yes, No or Cancel).
  • ShowSaveAsUI should display some way for the user to enter the context under which to save the document. For example, show a SaveFileDialog. The event arguments still allow the setting of a “Cancel” property to abort the save operation. There is also a property, Context, to save the filename or other save location.

The three properties are fairly self explanatory. ActiveView gets or sets the currently active IView object in the UI. Documents returns a ReadOnlyCollection, enforcing that all changes must be made through the interfaces methods, not directly on the collection. Views will return a ReadOnlyCollection of views for a given document.

The NewDocument and OpenDocument functions use a document factory to actually create or open a document. Once a document object is created it is added to the manager’s list of documents.

The save functions should examine the state of the document (via IsDirty and IsNew) and raise the necessary events to prompt the user and get the save context. In addition, EndEnd() should be invoked on each IView for the document.

… I have run out of time at the moment, but will continue this discussion at the next convenient point in time…


September 02, 2005

Aggregate Lists

Has anyone seen aggregate lists anywhere before?
What I mean is given multiple of lists of a business objects (of the same type), I want to have a list that contains all the objects from all the lists. Of course I require any changes in the source lists to be reflected in the aggregate list.
I've done some quick Googling, but found nothing in this area.

I may extend my BindingListView into a BindingAggregateListView that takes multiple IBindingList implementors. It would then be able to sort and filter over all the items.

Example of use:
Say I have 10 Customer objects and each customer has a list of Order objects. I want a form that displays all the orders from all customers (and lets me filter/sort the data). I don't really want to have extra code and queries that pull back a separate list of orders, since I want changes made to be put into the actual Customer's order item.
So an aggregate list of the existing Order lists would work great.


Google Ads

Search this blog

Most recent comments

  • I scratched my eye while i was holding some kind of plastic packaging.. Anyways the corner of the pl… by Ercan on this entry
  • About a year ago my contacts that i was wearing, i guess were fautly, because shortly after they wer… by Jon on this entry
  • I got shower gel in my eye 4 and a half days ago, and becasue i rubbed my eyes a lot, i have scratch… by Chris on this entry
  • This website may help http://www.webmd.com/eye–health/tc/Eye–Injuries–Home–Treatment by S on this entry
  • I somehow got dirt, or debris in my eye. The terrible pain sent me in a tailspin. I was afraid of sa… by Bobbi on this entry

Tags

September 2005

Mo Tu We Th Fr Sa Su
Aug |  Today  | Oct
         1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30      

Galleries

Blog archive

Loading…
Not signed in
Sign in

Powered by BlogBuilder
© MMXIV