Returning an Empty Object to a DetailsViewReturning an Empty Object to a DetailsView
Old forum URL: forums.lhotka.net/forums/t/1374.aspx
mtavares posted on Tuesday, October 03, 2006
I was just wondering if there was a way to get the CslaDatasource to return what would be considered an empty data row to the detailsview. I am trying to use the EmptyDataText property on the Detailsview, and it appears that just passing my blank BO isn't good enough. The Detailsview still thinks it is an actual data row instead of an empty one and therefore displays all of the fields with blanks instead of the EmpyDataText. Is there something I have to do in the BO to tell the Detailsview it is actually empty? Any help would be appreciated.
Thanks,
Mike
Jav replied on Tuesday, October 03, 2006
Try this.
Open DetailView --> Edit Templates --> Edit EmptyDataTemplate. Then in the little window type something like "No data available"
I don't work with DetailViews but I do use FormViews and GridViews and it works in those.
Jav
mtavares replied on Tuesday, October 03, 2006
Hi Jav,
Thanks for the response. Unfortunately, the problem for me is that the detailsview can't tell that my BO is empty, so it will never actually render what's in the EmptyDataTemplate. I'm looking for a way to let the DetailsView know that the BO being passed into it is the equivalent of an empty data row.
Thanks,
Mike
Jav replied on Tuesday, October 03, 2006
Aah, now that I re-read your question I see that you were already trying to do what I was suggesting. I assume that CslaDataSource in question is supposed to return an Object, not a Collection. If that is the case, you are coming up against an issue which may require handling in the Factory method.
What happens is this. You call your Shared Factory GetObject method. By the time the code gets to your DataPortal_Fetch, the object is already created with whatever values you assign to the object's instance variables. (This is obvious because, after all, the DataPortal_Fetch is a method of that very object). Now in DataPortal_Fetch when the call goes out to the database, it comes back empty handed, and you end up with your blank object back in the factory method, which is then returned to the UI.
I suppose what you would like to get back is "Nothing" or Null - in which case I expect that DetailView will show the EmptyDataView stuff. You can achieve that by examining the object in the Factory method as it comes back from the DataPortal_Fetch for some key Instance variables - like the LastName being blank, and then return "Nothing" if that's the case. Do make sure that your UI is aware of that and always checks for Nothingness of all such objects before trying to use them.
Jav
mtavares replied on Tuesday, October 03, 2006
So if I understand you correctly, if I determine the object passed back from my BO fetch to be a blank, then I should set the e.BusinessObject in the CslaDatasource to nothing. Unfortunately, that doesn't seem to work. I get the following error:
A data item was not found in the container. The container must either
implement IDataItemContainer, or have a property named DataItem.
Let me know if I misinterpreted your suggestion. It seems like there needs to be some mechanism to tell the detailsview that the object I'm passing to it is empty, but still be a valid object.
Thanks,
Mike
Jav replied on Tuesday, October 03, 2006
Mike,
No, I was assuming that you have access to the Business layer, and I was simply trying to explain the reason why you are getting a "blank" object (instead of a Null object) when no data was found in the database, and how to return Nothing from the Factory Method.
You cannot set CslaDataSource to nothing - that won't work as you already saw. Normally, here is how you use the CslaDataSource.
Protected Sub PersonDataSource_SelectObject(ByVal sender As Object, ByVal e As Csla.Web.SelectObjectArgs) Handles PersonDataSource.SelectObject
Dim obj As Person = GetPerson()
If obj IsNot Nothing Then
e.BusinessObject = obj
End If
End Sub
So in effect, normally, you leave e.BusinessObject alone if the Object returned from CslaDataSource is Nothing. Possibly you could try doing the same thing if the object returned is "blank"
Jav
mtavares replied on Tuesday, October 03, 2006
I follow what you are saying, but even with the code that you just showed me, if your Person object is nothing and you don't set it to the datasource, you will still get the error because if e.BusinessObject is never set, it is still nothing and therefore the error I displayed earlier will still be thrown.
I guess maybe the question I should be asking is how does the DetailsView know if something is a blank data row or not, and what can I do in my business object to make it think it is a blank data row.
Thanks,
Mike
Skafa replied on Tuesday, October 03, 2006
Concerncing the error message:
I've dealt with this before. The case is, when using CslaDataSource as the datasource on a *View Datasource / DataSourceID property, it tries to bind. And when it tries to bind, it expects a value. If it doesn't get a value, you get an error.
I'm not really into the internals of databinding or how rocky implemented CslaDataSource, but to avoid the error: do not databind if you know you have no object.
Jav replied on Tuesday, October 03, 2006
I just tried out a DetailsView for the first time. It lloks like:
- If DetailsView has the DataSourceID set, it expects valid data to be available
- It also looks like the DataKeyNames value must be set along with the DataSourcesID - if not, you will get an error
So here is what I did:
- Dragged a CslaDataSource on to the designer, and set its values
- Dragged a DetailsView on the designer and set its DataSourceID to CslaDataSource
- Clicked EditFields and set all the fields that I needed
- Went to properties window and deleted the DataSourceID to blank. It will ask if you want to regenerate the Fields - make sure to click NO
- Now in the code that I gave in my previous message, set the DetailsView's DataSourceID and the DataKeyNames in the same code block and after setting the e.BusinessObject - and only if the Object is not nothing
In my quick test, I did not get any error, the Detailsview did not even show up - presumably because I did not set up EmptyData info. I am assuming that when the object is valid, everything will show up.
Jav
mtavares replied on Tuesday, October 03, 2006
That is a workaround, but still doesn't get the detailsview to show the emptydatatext, it just doesn't display at all. Upon some digging into the CslaDatasource, I found a way to get it to work by changing some code in the ExecuteSelect Method. The original code had the following:
' if the result isn't IEnumerable then
' wrap it in a collection
If Not TypeOf result Is IEnumerable Then
Dim list As New ArrayList
list.Add(result)
result = list
End If
Now with the original code if result (the BO) is nothing, then when the control is bound to the detailsview that error occurs. But if I change it to:
' if the result isn't IEnumerable then
' wrap it in a collection
If Not TypeOf result Is IEnumerable Then
Dim list As New ArrayList
If result IsNot Nothing Then
list.Add(result)
End If
result = list
End If
Then I get the results I was looking for. the Details view will return the Empty Data Row because it is looking at an empty ArrayList instead of an arraylist with one item set to nothing. I decided to test this same thing out with a collection based BO with a gridview, and the results were still good where the Empty Data Row for the gridview was displayed. I also tried a bound dropdownlist and it was still ok.
So that being said, my next question if for Rocky: Are there any repercussions with only adding the result to the list if it is not nothing? My tests seemed to be fine, but I may not be accounting for something.
Jav replied on Tuesday, October 03, 2006
That's interesting. Mike you may want to post this in a separate thread so that Rocky will see it. That may be the answer to some of the tedious issues I have been facing with FormViews
Jav
Copyright (c) Marimer LLC