This project has moved. For the latest updates, please go here.

list/detail - more complex scenario

Apr 4, 2011 at 9:15 AM

Hi - once again, thanks for your efforts in this project. I still just don't think i understand this properly. It would really help me on my learning curve If I could provide a sample scenario and hear how you'd go about integrating the framework. I'll keep my scenario as simple as possible, but i understand if you don't have time to respond.

Scenario

Application with a Pivotal control on it's start screen. 3 Pivot items, each containing a short list of entities, let's call them Products. The first pivot item will contain a list of 'top' products, the second pivot item will contain a list of 'recently added' products, the third item contains 'bargain' products. Selecting a 'product' from any of these lists will take you to a details page.

On the server side, data for the  3 pivot item lists exist - a URI where using a different parameter keyword will return XML with the same Product schema, e.g http://sample.products.com?type=recent

Each of the three lists has slightly different caching requirements. For the recently added it should have a lifetime of 1 hour, for the top products it should be 1 day, and for the bargain products it should be 1 week.

The details view does not need to retrieve any additional information about a Product, apart from loading an Image.

 

So...

I could make some suggestions about how i've tried to implement this so far, but it doesn't feel like i'm with the pattern. I've tried to have 3 instances of the same ModelView for each of Lists because they're all showing the same kind of information - however, the cache requirements are different. Also, when a user wants to view the details - what do we bind the Details view to?

thanks for any suggestions!

Andrew

 

Apr 5, 2011 at 3:54 PM

I agree - the tutorials need to address a list/detail scenario as well.

Michael

Coordinator
Apr 7, 2011 at 9:50 AM
Edited Apr 7, 2011 at 9:53 AM

Hi there -

Yes, good question.  I'm traveling for a couple of weeks so samples will be slow to come by but let me outline how to do this.

Andrew for your scenario, because you need different caching periods you'll need three different ViewModel types.  

For your current case I'd do the following:

1) Create a base ModelItemBase-derived type to handle your data, let's call it ProductsViewModelBase.  This should have all of the properties on it you care about:

 

public class ProductsViewModelBase : ModelItemBase<LoadContext> {

   public string ViewType {

	get {

		return (string)LoadContext.Identity;

	}

}

protected ProductsViewModelBase(string viewType) : base(new LoadContext(viewType)) {

}

private ObservableCollection<ProductVm> _products = new Observable ...;
public ObservableCollection<ProductVm> Products {

  get {

	return _products;

}

set {

	_products.Clear();

     foreach(var p in value) {

     _products.Add(p);

    }

}



public class ProductsViewModelDataLoader : DefaultDataLoader {

	public LoadRequest GetLoadRequest(LoadContext context, Type objectType {

		// here we build the right URL based on the identity of the load context which is "top", "recent", etc.

		string url = String.Format("http://sample.products.com?type={0}", context.Identity);

     		return new WebLoadRequest(url);

	}

	public object Deserialize(...) {

		// deserialize the data to build a new ProductsViewModel of the right type



	ProductsViewModelBase vm = (ProductsViewModelBase)Activator.CreateInstance(objectType);

        vm.LoadContext = loadContext;



	// populate other values like products and whatnot, this assumes
        // only ID and Title come with the list.
         foreach (var item in productList) {
             vm.Products.Add(new ProductVm(item.ID, item.Title);
        }

	return vm;

       }

}

}

 

[this is all off the top of my head so excuse formatting, etc]

 

Now that you have this, derive three specific types with the right caching:

 

[CachePolicy(CachePolicy.CacheThenRefresh, 300)]
public class RecentProductsVm :ProductsViewModel {

  public RecentProductsVm () : base ("recent") {
  }
}


[CachePolicy(CachePolicy.CacheThenRefresh, 500)]
public class TopProductsVm :ProductsViewModel {

  public RecentProductsVm () : base ("top") {
  }
}

 

I have recently checked in a way to do dynamic cache times (see ICacheItem) but for now, this is the tested and verified way of doing it so maybe give this a shot first.

Now on details, note that the item type in the ObserableCollection is ProductVm.  That's how you do the details.  This depends on how much data you get with your list request.  Meaning, if you get all of the info you care about in the list request, then you can just create the full ProductVm there.

Otherwise, if there is a secondary details request "http://sample.products.com/productid=1234", then you'll build a second class deriving from ModelItemBase to represent the product details.

The way to usually do this a little more complicated but basically you can use the loader to load additional values into an object, something like this:

 

public class ProductVm : ModelItemBase<LoadContext>() {

   public string Title {...}


public string Description {

     get {

          if (_desc == null) {

              // we know that we've gotten a request for more info so
              // set this object as a proxy, then kick off a load.  AgFx
              // will then update this object's properties.
              
              DataManager.Current.RegisterProxy(this);
              DataManager.Current.Load<ProductVm>(this.LoadContext);
          }
	  return _desc;
     }

}

    public ProductVm(int productId, string title) : base(new LoadContext(productId) {
    Title = title;
}

// DataLoader similar to above...

}

 

With the above, when you databind to the "Description" property in a listBox ItemTemplate or whatever, it'll kick off the full load for the detailed item.  Same if you you had another details page, etc.  I'll do a bigger sample when I get a chance, hopefully this gives you enough to get moving.


Shawn

Coordinator
Apr 20, 2011 at 7:53 PM

Hi Brooky - did this resolve your question?

Jun 11, 2011 at 7:53 PM

Hey Shawn,

Sorry I've taken so long to reply to this. Silly work getting in the way of hobbies :)

Yes, your response helped me make significant progress.

thanks,

Brooky 

Coordinator
Jun 14, 2011 at 4:26 PM

Great.  Also note that ICacheItem is now in the bits, you can use that to dynamically assign expiration times.