This project is read-only.

HideMyProperty() in list view

Jun 29, 2012 at 6:46 PM

Hi.

If I have a HideMyProperty() method on my entity, and it correctly hides MyProperty in object view, is it not supposed to also hide it in list view? It doesn't.

Although properties marked up with [Hide] are hidden in both views.

Jun 29, 2012 at 7:03 PM

Assuming that you are referring to a table view, then, HideXxxProperty() alone will not cause the column to be hidden.  This is because a HideXxx method is dynamic  -  the hiding may vary between instances and according to the state of the object.  The table-renderer has to assume that some of the objects in its view might have that property visible.  

If a property is marked [Hidden] or if the property is rendered invisible to the user via the framework's authorization mechanism, then the column will not be rendered.

I suppose it would be possible to arrange that in a table view where the column was shown then if that property was invisible for a given row then it could be rendered as, say 'Hidden'.  (Note that it could not simply be blanked as this could be confused with the property being null/empty).  But this might not be acceptable to all.

Possible workarounds would be:

1. Use a custom view to remove that column in your view.

2. Return the collection as defined by an interface that reveals only the properties of interest.

 

 

 

 

Jun 29, 2012 at 7:36 PM
Ok. That makes sense about the different instances.
Was hoping to stay away from custom views as much as possible.
Will check out the interface approach.
Jun 29, 2012 at 7:47 PM

Ok, how do I do it?

I created a new interface, IIndividualListView, and exposed only the properties that I want to display.

Now my repository returns it like this:

        public IQueryable<IIndividualListView> ListAllIndividuals ()
        {
            return
                from individual in Container.Instances<Individual> ()
                select individual;
        }

Everything runs fine, but it still displays all the properties on the Individual entity in the list.

Jun 29, 2012 at 10:08 PM
Edited Jun 29, 2012 at 10:09 PM

I think you might have to explicitly cast it.  Something like:

return Container.Instances<Individual>().Cast<IIndividualListView>();

Otherwise what is actually being passed to the viewer is still an IQueryable<Individual>

Jun 30, 2012 at 8:58 AM

Then I get.

 

Unable to cast the type 'SmdCoreModel.Individual' to type 'SmdCoreModel.PartialEntities.IIndividualListView'. LINQ to Entities only supports casting Entity Data Model primitive types.

Jun 30, 2012 at 10:59 AM

Sorry  -  I was trying to help you from memory yesterday.

I can see now why that wouldn't work  -  because returning an IQueryable is still dealing with Linq to entities at that point.

You can definitely do this if you are returning a collection or other IEnumerable (e.g. by adding .ToList() ) rather than an IQueryable  -  but then you won't get the paging capability at the UI.

Jun 30, 2012 at 11:31 AM

"You can definitely do this if you are returning a collection or other IEnumerable (e.g. by adding .ToList() ) rather than an IQueryable  -  but then you won't get the paging capability at the UI."

Yes, losing the paging ability is not really an option, but just for testing, I did this:

        public IEnumerable<IIndividualListView> ListAllIndividuals ()
        {
            return
                (from individual in Container.Instances<Individual> ()
                 select individual).Take (40).ToList ().Cast<IIndividualListView> ();
        }

That did not throw the exception, but again displayed all the properties in the list, not only the ones on the interface.

Besides that, I do not see how explicitly casting could make a difference. The method returns IIndividualListViews. So the calling code will have references to IIndividualListViews whether there was an explicit cast or not. Not so?

Jun 30, 2012 at 1:08 PM

Sorry  -  I gave you the wrong syntax hint.  Using the Cast like that doesn't alter anything; it should be:

return Container.Instances<Individual>().Take(40).ToList<IIndividualListView>();

(I just tried out a similar example and confirmed that it does work).

"So the calling code will have references to IIndividualListViews whether there was an explicit cast or not. Not so?"

No.  The UI is entirely generic so it doesn't know about any of your domain code.  The UI simply reflects over the objects that it is being given (that's a simplified explanation, but the principle is right).  Even if the method signature returns X, what the viewer will reflect over is the actual .NET type that is returned (which must conform to X, obviously), which in your code was still in fact a List<Individual>. You could verify that by putting in a break-point and examining the returned object.

If you think about it, that's always true in .NET  -  even if a method signature returns type Ixxx,  the calling code can still test the actual type of the returned object, and even cast it back to that type (not that that would be good practice, obviously!)

Jul 1, 2012 at 11:38 AM

"return Container.Instances<Individual>().Take(40).ToList<IIndividualListView>();"

Ok, that worked. Pity that it is not possible with the IQueryable. I'll have to go with a custom view.

Just FY, the paging still works on the UI with the interface approach above, but obviously it has to load the full recordset from the DB each time.

 

"No.  The UI is entirely generic so it doesn't know about any of your domain code.  The UI simply reflects over the objects that it is being given (that's a simplified explanation, but the principle is right).  Even if the method signature returns X, what the viewer will reflect over is the actual .NET type that is returned (which must conform to X, obviously), which in your code was still in fact a List<Individual>. You could verify that by putting in a break-point and examining the returned object."

You are correct, of course. :)