Link to home
Start Free TrialLog in
Avatar of abulka
abulka

asked on

Basic Doc-View explanation

Could someone explain the basic mechanics of the Document View architecture?
Is it true that the "View" is a GUI control/widget and a "Document" is a OO model?

Is it possible then, to associate a specific model object attribute e.g. customer1.name with a GUI static text control using document/view?  Or is that too fine grained?

thanks,
-Andy
Avatar of Zoppo
Zoppo
Flag of Germany image

Hi abulka,

This is from MSDN:

---------------------------------------------------------------------------------------------------------------------
The CDocument class provides the basic functionality for programmer-defined document classes. A document represents the unit of data that the user typically opens with the Open command on the File menu and saves with the Save command on the File menu.

The CView class provides the basic functionality for programmer-defined view classes. A view is attached to a document and acts as an intermediary between the document and the user: the view renders an image of the document on the screen and interprets user input as operations upon the document. The view also renders the image for both printing and print preview.
---------------------------------------------------------------------------------------------------------------------
(search MSDN index for 'MFC document/view architecture' and see related articles)

associating an object from the document to the view as you mentioned is only possible by setting the data in the view's OnInitialUpdate() and updating the data in the view's OnUpdate(). Direct association is difficult because a document can have multipe views.

hope that helps,

ZOPPO
Avatar of andymurd
andymurd

MSDN can be a bit wordy and technical - so here's an example. Think of a document which is a load of sales figures for lots of different salespersons. There are many different ways to view this info:

* A graph of the performance of each salesperson.
* A Table (like Access) which allows the data to be edited.
* A Report
etc

The document doesn't change but it has different views applied to it.

Similarly, if you wanted to store that sales figures in a database instead of a file, the same views could be applied to a different document class (if the coders weren't lazy and provided proper accessor functions).

If you've heard of the model/view/controller design pattern, document view is kind of like that.
Avatar of abulka

ASKER

I am familiar with MVC, and other similar patterns.  So with Doc/View - assuming I have 3 'business objects' (3 customer objects) and I want to display them on a form.  What would be the basic steps?  Here is my guess:

1. Derive CCustomer from CDocument?
2. Derive a form from CView?
3. Register the form as an 'observer' of each customer object e.g.
  form1.attach( cust1 );
  form1.attach( cust2 );
  form1.attach( cust3 );
4. In the form1.OnUpdate ask
  if updateType = 'some type of interest'
      editgui1.text = cust1.name;
      editgui2.text = cust1.phone;
      editgui3.text = cust1.address;

I have taken some liberties with names and methods, and stand to be corrected.  I hope the gist of what I am doing is right though - is it?
Hi abulka,

this depends on what you wanna do:

seems that you wanna try to put multiple documents together with one view. This is not possible. You can only have multiple views for one document. So, I would suggest something like this:

- create a class for data you need to hold called CCustomer (you can derive this from CObject to give the class standard MFC serialization functionality)
- create a document class derived from CDocument, i.e. CCustomerDoc and there implement a container for CCustomer objects, i.e. a CArray or a CList or a CMap.
- override the documents Serialize() function and implement loading and saving of this CCustomer container.

Next steps depend on what type of view-design you like to have:

1. You can create a single formview for all customers, or
2. you can create a formview for one customer and some selection functionality (i.e. select customer with dialog or a split window with a list or a tree holding the customers)

BTW, at very first you'll have to decide if you app should be MDI or SDI. Think about this carefully. It's nearly impossible (or at least very hard) to re-design an SDI app as MDI or vice versa. Think about all the pros and contras for both.

hope this helps,

ZOPPO
Avatar of abulka

ASKER

Ok - Zoppo - that's a most useful comment.  It seems you need to have one single 'document' object that aggregates all the business objects in the model.  Would that be a correct way of phrasing it?

And finally, could you say just a little more about the form side of things. e.g.

4. In the form1.OnUpdate ask
  if updateType = 'some type of interest'
      editgui1.text = cust1.name;
      editgui2.text = cust1.phone;
      editgui3.text = cust1.address;

(my above pseudo code is my current understanding of what goes on).  I would suspect that some notification happens (an event handler?) and that information (via a parameter?) is passed saying WHICH particular business object (and what aspect?) of it has changed.  Then it is up to the form code to decide what to do with it?  Is that the gist of it?
Now, I assume with 'form' you mean some dialog like input mask (with edit controls, buttons, combo boxes and so on...), so using a CFormView is best way to do this. For this do following:

When start creating your app in the last pane of the AppWizard you can select the base class of your application's view class. Select CFormView. Then AppWizard creates an empty dialog resource which will be used as template for the formview. There add the controls you need, give them senseful resource IDs and add member variables for the controls with ClassWizard (i.e. a CString m_CustomerName as member variable for the edit box you want to use for the customer's names).
So you can now simply set/get the edit box's text somehow like this:

// get text entered to edit box
UpdateData( TRUE );
// now the entered text is in m_CustomerName...

// set text to edit box
m_CustomerName = "NewCustomer";
UpdateData( FALSE );

You just have to take a little bit care because all controls which has a member variable attached are updated when UpdateData() is called, so no way to pass any hint which controls need update.

Then you can implement a OnUpdate() function for the view which gets passed a pointer to a view(pSender), a LPARAM(lHint) and a pointer to a CObject(pHint). The LPARAM can be used to pass control values to the function, the COpbject pointer can be used to pass data to the function. This function is called for every view (except the view passed as pSender if pSender not zero) when CDocument::UpdateAllViews() is called. So you can implement it somehow like this:

#define UPD_HINT_GET_VALUES 1
#define UPD_HINT_SET_VALUES 2

CMyView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
 CMyDoc* pDoc = GetDocument();
 if ( lHint & UPD_HINT_GET_VALUES )
 {
  UpdateData( TRUE );
  // here you can set the data in the document with the entered data of the form view
 }

 if ( lHint & UPD_HINT_SET_VALUES )
 {
  // here you can set the form view's data with the data of the document
  UpdateData( FALSE );
 }
}

now, the only thing you'll have to do when i.e. selecting a new customer is something like:

CMainFrame::OnSelectNewCustomer()
{
 CView* pView = GetActiveView(); // this is for SDI, for MDI you'll have first to get the active view's child frame with MDIGetActive()
 CMyDoc* pMyDoc = (CMyDoc*)pView->GetDocument();

 // first update the data eventually entered for the previous customer
 pView->OnUpdate( NULL, UPD_HINT_GET_VALUES, NULL );

 // next set new values to the view(s)
 pMyDoc->UpdateAllViews( NULL, UPD_HINT_SET_VALUES, NULL );
}


Any further stuff (especially the messages you need to handle) strongly depends on how you design you application. Some messages need to be handled completely different for SDI and MDI. Further you'll need any possibility to select a customer from the documents customer list, i.e. simply through a combo box in the form view or even more complex through a list(or tree) view in an extra pane of a splitted window (somehow like explorer window).

ok, that's nearly all I can say without more info.

hope my description sounds meaningful,

ZOPPO
Avatar of abulka

ASKER

Adjusted points from 50 to 75
Avatar of abulka

ASKER

That's great - just the sort of stuff I wanted to know.  I'll accept your last answer.  Just one more thing... (I've bumped the points a little higher)

I've heard an argument to say that its sometimes useful to introduce a class that sits in between the view and the doc.  This intermediate class inherits from view, rather than a form having to inherit from view.  The intermediate class would encapsulate and manage the view behaviour.  Its sort of like an adaptor or mediator.  It saves you from having to have the form inherit from view and keeps the form clean.  What do you think of this idea?  Especially the sentence:
  "DV users often avoid sub-classing GUI controls by introducing an adapter class which inherits from the ‘view’ class."

Also, have you heard of the DocManager class in this framework?  I don't know what it does...  Could this DocManager class be doing anything like the mediation/adaptor role described above.  Or is the DocManager class just an aggregate/ manager for document objects?

thanks for any thoughts.
Hmm, I'm not sure if I really understand what this 'adaptor'-class should do ... would be good if you could explain this with a little pseudo code. BTW, I think it's mostly a good idea to implement a clean interface class for related classes.

CDocManager is just a kind of interface class used by the CWinApp class to handle document templates and default document-dependant functionality

ZOPPO
Avatar of abulka

ASKER

Adjusted points from 75 to 80
Avatar of abulka

ASKER

(sorry for the delay in my repsonding to this thread...)

The CandyCustomAdaptor adapter class would implement the 'view' interface and forward things onto a regular form.

This would alleviate the need for the visual form to know about doc/view or having to inherit/implement view.

So what I am basically asking is: is this a common/useful/workable technique?  Some doc/view programmer friend of mine reckons he does it.
This question has been undeleted.  The points for this question were originally 80 but have been reduced to 0
Adjusted points from 0 to 80
Restoring question.

darinw
Customer Service
Avatar of abulka

ASKER

zoppo - could you comment on my last comment so that I can award your points and close this thread?  thanks for your patience on the slow progress on this one.
-Andy
ASKER CERTIFIED SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of abulka

ASKER

Answer accepted