I have looked through "The Dolphin Smalltalk Companion" as well as some
other examples (like PersonalMoney) but can't seem to get a handle on how to populate a multiple column object in a view. Specifically this is an extended list presenter in Dolphin X6. As an example I populate two different ListModels with information. One of them collects document numbers. Then the other one collects document dates. They are two different ListModels. If I create a extended list presenter I can only populate the first column with information. To do so I just change the name of the presenter to be the document number variable. If I try to add a second column I don't know how to get the information across using getContentsBlock. If I don't use getContentsBlock the second column just repeats the elements that are presented in the first one. Any newbie examples anyone can pass along? |
gregarican wrote:
> As an example I populate two different ListModels with information. One > of them collects document numbers. Then the other one collects document > dates. They are two different ListModels. You can't make a ListPresenter show two different ListModels. They are designed to show /one/ list, with each column showing a different "aspect" of the element in each position. There are several ways to get the result you want. Probably the easiest is to have an object with contains all the data you want to display in each row, and then use a list of those. Chances are that if you have such closely associated data in your domian, then you want some object which relates them anyway. If that's unsuitable, then you can do it with a level of indirection. Store indexes in the ListPresenter's model, and use those to access the "real" listss. E.g: "set up a model" l1 := #( dog cat elephant ). l2 := #( Fido Tiddles Rosy ). m := ListModel on: (1 to: 3). "show a list with two columns" lp := ListPresenter show: 'Enhanced list view' on: m. lv := lp view. lv addColumn. "make the columns refer back to the other two lists" (lv columnAtIndex: 1) getContentsBlock: [:i | l1 at: i]. (lv columnAtIndex: 2) getContentsBlock: [:i | l2 at: i]. Typically you wouldn't need all that code since you'd set most of it up in the View Composer, but the idea's the same. -- chris |
In reply to this post by gregarican
gregarican,
> As an example I populate two different ListModels with information. One > of them collects document numbers. Then the other one collects document > dates. They are two different ListModels. All the information passed to the ListPresenter must be accessible through one collection. Use the #getContentsBlock to access the column information for each row. > Any newbie examples anyone can pass along? Some simple examples. I'll show them in workspace code but it should be readily translatable to a ListPresenter/View setup. collection := OrderedCollection with: 1@2 with: 3@4 with: 5@6 with: 7@8. lp := ListPresenter show: 'Enhanced list view' on: collection. "Evaluating the above shows a list view with one column, and the points being displayed in that column. Now add a second column" lp view addColumn: (ListViewColumn text: 'Y'). "Evaluating all the above now gives two columns, both containing all the points. This is because the #getContentsBlock defaults to answering the object in the collection (a Point)" lp view primaryColumn text: 'X'. lp view primaryColumn getContentsBlock: [:item| item x]. (lp view columnAtIndex: 2) getContentsBlock: [:item| item y]. "Now evaluating all the above puts the x values in the first column and the y values in the seconds column. This is because you have told each column how to obtain its contents from the underlying object. Another example collection := OrderedCollection with: 'abc' with: 'def' with: 'ghi' with: 'jklm' with: 'no'. lp := ListPresenter show: 'Enhanced list view' on: collection. lp view getImageBlock: nil. lp view primaryColumn text: 'First'; getContentsBlock: [:item | item first]. lp view addColumn: ( (ListViewColumn text: 'Rest') getContentsBlock: [:item | item copyFrom: 2]; yourself) And one final one, with index/date contained ina collection of associations (one of many ways) collection := OrderedCollection with: 1 -> (Date fromString: '1/1/2006') with: 2 -> (Date fromString: '1/2/2006') with: 3 -> (Date fromString: '1/3/2006') with: 19 -> (Date fromString: '1/4/2006'). lp := ListPresenter show: 'Enhanced list view' on: collection. lp view getImageBlock: nil. lp view primaryColumn text: 'Index'; getContentsBlock: [:item | item key]. lp view addColumn: ( (ListViewColumn text: 'Date') getContentsBlock: [:item | item value]; yourself) There's a _lot_ more you can do with ListView though - this is just the basics. -- Ian Use the Reply-To address to contact me (limited validity). Mail sent to the From address is ignored. |
Thanks everyone for all of the help. This has really filled in the
blanks for me! |
Just to clarify one thing which might cause a bit of confusion.
In Chris' example he passed a ListModel as the model for the ListPresenter whereas I used an OrderedCollection. In this situation both will work but Chris' version is correct and will prevent future walkbacks occurring when more complex use is made of the MVP triad. In "proper" code, i.e. not simplified workspace examples, the issue doesn't normally crop up as the creation of the ListPresenter and it's population would usually be done in different places. Personally I don't use a new ListModel but update the existing ListModel contents - but that's just a personal preference. I would tend to use createComponents [] listP := self add: ListPresenter new name: 'whatever' and somewhere else do listP list: myInitialCollection but listP model: (ListModel on: myInitialCollection) is just as valid. The only difference (I think) is that the first version will resort the list according to the ListPresenter's sort criteria but the second won't. -- Ian Use the Reply-To address to contact me (limited validity). Mail sent to the From address is ignored. |
Ian,
> listP list: myInitialCollection > > but > > listP model: (ListModel on: myInitialCollection) > > is just as valid. The only difference (I think) is that the first > version will resort the list according to the ListPresenter's sort > criteria but the second won't. FWIW, I usually use the first form too. IIRC it causes less flicker than changing the model. Of course, there are times when I have to set the model explicitly, e.g. if I want two ListPresenters to share a model, or when I use one of my DerivedListModels. -- chris |
Free forum by Nabble | Edit this page |