Wrox Programmer Forums

Need to download code?

View our list of code downloads.

| FAQ | Members List | Search | Today's Posts | Mark Forums Read
BOOK: ASP.NET 2.0 Website Programming Problem Design Solution ISBN: 978-0-7645-8464-0
This is the forum to discuss the Wrox book ASP.NET 2.0 Website Programming: Problem - Design - Solution by Marco Bellinaso; ISBN: 9780764584640
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: ASP.NET 2.0 Website Programming Problem Design Solution ISBN: 978-0-7645-8464-0 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
DRM-free e-books 300x50
 
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old February 8th, 2009, 06:20 PM
Authorized User
 
Join Date: Mar 2007
Location: , , Denmark.
Posts: 52
Thanks: 6
Thanked 2 Times in 2 Posts
Default Passing articleID to ObjectDataSource..

I’m working on tags for my articles. Everything is pretty much working now. I can create tags, and when I create a new article, I have the available tags listed in a checkbox list, so I can check the ones I want associated with my article. When I hit save, everything is saved correctly in the database.



Now, I want to show the tags for each article in the articles listing, and this is where I’m a little stuck. I have built my article list with a ListView. I have made a class Tag, which has a GetTagsByArticle method. So, I put an ObjectDataSource control on the page and set my Tag class as type for it. Then In my ListView, I tried to put a BulletedList control and hook it up to my ObjectDataSource. When I run the page, I get no output.



To test it, I tried to set a default value for the asp:Parameter to an articleID that exists in the database, and this works, it writes out all the tags for that particular article. Of course, this is not how it should be, it should write out the tags for each article, so I need to get the articleID for the current article in each loop of the ListView.



So far, I have been using Eval to get the values from the ObjectDataSource. I feel like this should be as easy as hooking the Datacontrol up to the ObjectDataSource, but I can’t figure it out. Maybe I have been staring myself blind on it…
Any ideas?

This is the code for the ObjectDataSource.

<asp:ObjectDataSource ID="ObjTags" runat="server" SelectMethod="GetTagsByArticle"
TypeName="SG.Blog.BLL.Articles.Tag" OldValuesParameterFormatString="original_{0}">
<SelectParameters>
<asp:Parameter Name="articleID" Type="Int32"/>
</SelectParameters>
</asp:ObjectDataSource>
  #2 (permalink)  
Old February 10th, 2009, 12:11 PM
Lee Dumond's Avatar
Wrox Author
Points: 4,942, Level: 29
Points: 4,942, Level: 29 Points: 4,942, Level: 29 Points: 4,942, Level: 29
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2008
Location: Decatur, IL, USA.
Posts: 923
Thanks: 12
Thanked 166 Times in 162 Posts
Default

Not sure I understand the question.

Are you saying that you want a list of articles, and for each article in the list, you want to display a list of relevant tags for that article in a bulleted list? Kind of like this?:

Article: My Favorite Websites
  • personal
  • web
Article: Good Places to Stay
  • vacations
  • hotels
  • reviews
Article: Interview with Valentino Rossi
  • interviews
  • motorcylces
  • racing
__________________
Visit my blog at http://leedumond.com
Follow me on Twitter: http://twitter.com/LeeDumond

Code:
if (this.PostHelpedYou)
{
   ClickThanksButton(); 
}
  #3 (permalink)  
Old February 10th, 2009, 12:34 PM
Authorized User
 
Join Date: Mar 2007
Location: , , Denmark.
Posts: 52
Thanks: 6
Thanked 2 Times in 2 Posts
Default

Hey Lee.

Not specifically a bulleted list. My problem is that I don't get any output from the Tag ObjectDataSource at all. For instance, I tried putting in a ListView, and hooking that up to the ObjectDataSource (the code I posted) and this gives me no output. However, when I set a default value for an articleID in the parameter element in the ObjectDataSource, I get the tags written out for that article. So it seems that it works, but I can't get the right articleID to the ObjectDataSource. I have no idea why...
Code:
        <SelectParameters>
            <asp:Parameter Name="articleID" Type="Int32"/>   
       </SelectParameters>

Gives no output in the ListView
Code:
   <SelectParameters>
        <asp:Parameter Name="articleID" Type="Int32" DefaultValue="9"/>
      </SelectParameters>

Writes the tags from article ID = 9.
This is the ListView I tested with:
Code:
<asp:ListView ID="ListViewTags" runat="server" DataSourceID="ObjTags" ItemPlaceholderID="tags"
                                DataKeyNames="ID">
                                <LayoutTemplate>
                                    <asp:PlaceHolder runat="server" ID="tags"></asp:PlaceHolder>
                                </LayoutTemplate>
                                <ItemTemplate>
                                    <span>
                                        <asp:Label ID="Label1" CssClass="" runat="server" Text='<%# Eval("TagName") %>'></asp:Label></span>
                                </ItemTemplate>
                            </asp:ListView>
Soeren...
  #4 (permalink)  
Old February 10th, 2009, 01:06 PM
Lee Dumond's Avatar
Wrox Author
Points: 4,942, Level: 29
Points: 4,942, Level: 29 Points: 4,942, Level: 29 Points: 4,942, Level: 29
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2008
Location: Decatur, IL, USA.
Posts: 923
Thanks: 12
Thanked 166 Times in 162 Posts
Default

I must be stupid today.

I think I kinda get it, but I am still having a hard time getting a "picture" of what you want the output to look like. Can you show a rough idea of the final rendering you're going for here?

Part of the problem I am having a hard time picturing this is that you're wrapping the label in a span tag, and Labels are already rendered with <span>, so you would end up with <span><span> here. Plus, it looks like there's no separation between tag names?

Sorry...
__________________
Visit my blog at http://leedumond.com
Follow me on Twitter: http://twitter.com/LeeDumond

Code:
if (this.PostHelpedYou)
{
   ClickThanksButton(); 
}
  #5 (permalink)  
Old February 10th, 2009, 01:31 PM
Authorized User
 
Join Date: Mar 2007
Location: , , Denmark.
Posts: 52
Thanks: 6
Thanked 2 Times in 2 Posts
Default

Not at all Lee, I really appreciate all the help you provide :-)

I know the code I provided looks a little weird, but it is mostly test code, which allways looks kinda weird :-D So far, I have been trying with a ListView and a BulletedList, but I can't get any output from the ObjectDataSource, not without providing a default value, which is not what I want. Doing so, shows me that my BLL/DAL/Database works fine, and that I have, apparently, configured my ObjectDataSource/ListView correctly.

The problem is getting the articleID to the GetTagsByArticle method, in every loop of the ListView. I thought this was just a matter of hooking the ListView up to the ObjectDataSource. It works in all the other pages I have used ObjectDataSource/ListView.

My problem is not so much with layout, but more with getting som sort of output to layout :-) My final layout would be like most other blogs, with the tags shown somewhere in the bottom of each entry. But again, this comes later.

Soeren
  #6 (permalink)  
Old February 13th, 2009, 12:29 AM
Lee Dumond's Avatar
Wrox Author
Points: 4,942, Level: 29
Points: 4,942, Level: 29 Points: 4,942, Level: 29 Points: 4,942, Level: 29
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2008
Location: Decatur, IL, USA.
Posts: 923
Thanks: 12
Thanked 166 Times in 162 Posts
Default

Dude... I stared at this for about an hour before I finally figured out what you were trying to do and why it doesn't work.

Once I got my head around it, I was able to whip up a quickie app on my end, and it works awesome. The way I did it was to use a nested ListView -- where the list of articles is a ListView, and the lists of tags is also a ListView nested inside of the Articles list.

Is that what you are looking for?

(Hint: You don't bind the inner ListView with an ObjectDataSource, only the outer one...)
__________________
Visit my blog at http://leedumond.com
Follow me on Twitter: http://twitter.com/LeeDumond

Code:
if (this.PostHelpedYou)
{
   ClickThanksButton(); 
}

Last edited by Lee Dumond; February 13th, 2009 at 12:32 AM..
  #7 (permalink)  
Old February 13th, 2009, 10:37 AM
Authorized User
 
Join Date: Mar 2007
Location: , , Denmark.
Posts: 52
Thanks: 6
Thanked 2 Times in 2 Posts
Default

Quote:
Originally Posted by Lee Dumond View Post
The way I did it was to use a nested ListView -- where the list of articles is a ListView, and the lists of tags is

also a ListView nested inside of the Articles list.

(Hint: You don't bind the inner ListView with an ObjectDataSource, only the outer one...)
Thats exactly how I did it, only difference is that I also bound the inner ListView to an ObjectDataSource. I have a class Tag, and this class has a method "GetTagsByArticle". So, I made that the select method, and then the Tag class as Type in this ObjectDataSource.

The problem I'm having is that the inner ListView doesn't seem to know which article ID to use. I have the DataKeyNames property set to "ID".

However, if I provide the Tag ObjectDataSource with a default value for the select parameter, it works (but only for that particular articleID).

I bind the outer ListView to an ObjectDataSource to get the articles, and the inner ListView to an ObjectDataSource to get the tags for each article.

So, the outer ListView uses GetArticles in the Article class to write the data for each entry in the articles list, and when it reaches the inner ListView, this uses the GetTagsByArticle(articleID) to write the tags for that particular article. I want the articleID for GetTagsByArticle to be that of the current article which is being written by the outer ListView, and this is where I'm stuck. It's like these two ListViews need to be syncronized somehow...

In my design, I decided to create a class for tags, like the ones for comments and categories. Therefore, it felt natural to have one ObjectDataSource for articles, and another one for tags, but since the tags are written in a nested ListView, apparently this is harder than I thought.
I have this many-to-many relationship between the articles and the tags, and it works fine.

I hope you understand the nonsense I'm writing, but hey, I'm Danish :-D

Again, thanks so much for all the help...
  #8 (permalink)  
Old February 13th, 2009, 12:22 PM
Lee Dumond's Avatar
Wrox Author
Points: 4,942, Level: 29
Points: 4,942, Level: 29 Points: 4,942, Level: 29 Points: 4,942, Level: 29
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2008
Location: Decatur, IL, USA.
Posts: 923
Thanks: 12
Thanked 166 Times in 162 Posts
Default

Quote:
Originally Posted by philthy View Post
Thats exactly how I did it, only difference is that I also bound the inner ListView to an ObjectDataSource. I have a class Tag, and this class has a method "GetTagsByArticle". So, I made that the select method, and then the Tag class as Type in this ObjectDataSource.

I bind the outer ListView to an ObjectDataSource to get the articles, and the inner ListView to an ObjectDataSource to get the tags for each article.
Yes, this is exactly how I envisioned it, and it is exactly the first approach I tried. And (no surprise!) I had the same problem you had.

So then, I figured I would intercept the ItemDataBound event on the outer ListView, grab the inner ListView from the Controls collection, grab the articleID from the eventargs, and pass it in that way. No joy there though, because once ItemDataBound has fired on the outer list, it's too late to bind the inner list.

Then I finally figured out how to do this the right way. The key is NOT to bind the inner list to a datasource at all, but to bind the inner list to a property of the outer list item using a data expression. That way, when the outer list item is databound, it will bind the innerlist at the same time, all in one pass.

Here is the page:

Code:
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
   <title>Articles</title>
</head>
<body>
   <form id="form1" runat="server">
      <div>
         <asp:ListView ID="lstArticles" runat="server" DataSourceID="objArticles"
            ItemPlaceholderID="itemPlaceHolder1">
            <ItemTemplate>
               <p>
                  <asp:Label ID="lblArticleTitle" runat="server" Font-Bold="true"
                     Text='<%# Eval("Title") %>' />
                  <br />
                  <asp:Label ID="lblPublishedDate" runat="server" Font-Italic="true"
                     Text='<%# Eval("PublishedDate","{0:MMM d, yyyy}") %>' />
                  <br />
                  Tags:
                  <asp:ListView ID="lstTags" runat="server" ItemPlaceholderID="itemPlaceHolder2"
                     DataSource='<%# Eval("Tags") %>'>
                      <ItemTemplate>
                        <asp:Label ID="lblTagName" runat="server" Text='<%# Eval("TagName") %>' />
                     </ItemTemplate>
                     <LayoutTemplate>
                        <asp:PlaceHolder ID="itemPlaceHolder2" runat="server" />
                     </LayoutTemplate>
                  </asp:ListView>
               </p>
            </ItemTemplate>
            <LayoutTemplate>
               <asp:PlaceHolder ID="itemPlaceHolder1" runat="server" />
            </LayoutTemplate>
         </asp:ListView>
         <asp:ObjectDataSource ID="objArticles" runat="server" SelectMethod="GetArticles"
            TypeName="LD.Blog.Article" />
      </div>
   </form>
</body>
</html>
Note that the inner list (lstTags) is not bound to a data source, but is instead bound using the following databinding expression:

Code:
DataSource='<%# Eval("Tags") %>'
Tags is a property of Article that uses the GetTagsByArticle method to get its value.

Code:
namespace LD.Blog
{
   public class Article
   {
      public int ArticleID { get; set; }

      public string Title { get; set; }

      public DateTime PublishedDate { get; set; }

      private List<Tag> tags;

      public List<Tag> Tags
      {
         get
         {
            if (tags == null)
            {
               tags = Tag.GetTagsByArticle(this.ArticleID);
            }

            return tags;
         }
      }  

      public static List<Article> GetArticles()
      {
         // snipped out         
      }
   }
}
The "Tags" databinding expression is evaluated at the same time as "Title" and "PublishedDate" -- that is, when each Article item is fetched. The inner list then binds to Tags, which internally uses GetTagsByArticle(), just like the ObjectDataSource would have, except it does it at the right time -- when the Article data is actually available.

I tried this with some fake data and it works, so I hope that helps you out. If you need, I can zip the whole thing up and email it to ya.

Have fun.
__________________
Visit my blog at http://leedumond.com
Follow me on Twitter: http://twitter.com/LeeDumond

Code:
if (this.PostHelpedYou)
{
   ClickThanksButton(); 
}
The Following User Says Thank You to Lee Dumond For This Useful Post:
philthy (February 14th, 2009)
  #9 (permalink)  
Old February 13th, 2009, 08:58 PM
Authorized User
 
Join Date: Mar 2007
Location: , , Denmark.
Posts: 52
Thanks: 6
Thanked 2 Times in 2 Posts
Default

Amazing man... That works

I also tried the ItemDataBound trick, and also tried with some other events, with no luck ofcourse. I also considered trying the Tags property in the articles class, but I really felt that hooking my Tag class to the ObjectDataSource should work.

But, even if I had used the Tags property, I wouldn't have considered using DataSource='<%# Eval("Tags") %>' for the inner ListView like you suggested. I would have been close.... Close but no cigar...

This is really a great learning experience.

I want to thank you again for the excellent help, really awesome
  #10 (permalink)  
Old February 14th, 2009, 03:21 PM
Lee Dumond's Avatar
Wrox Author
Points: 4,942, Level: 29
Points: 4,942, Level: 29 Points: 4,942, Level: 29 Points: 4,942, Level: 29
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2008
Location: Decatur, IL, USA.
Posts: 923
Thanks: 12
Thanked 166 Times in 162 Posts
Default

Don't forget to click the Thanks button. I need all the ego boosts I can get. ;-)
__________________
Visit my blog at http://leedumond.com
Follow me on Twitter: http://twitter.com/LeeDumond

Code:
if (this.PostHelpedYou)
{
   ClickThanksButton(); 
}
The Following User Says Thank You to Lee Dumond For This Useful Post:
 


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ObjectDataSource in UserControl Colonel Angus .NET Framework 2.0 0 April 3rd, 2008 10:14 AM
ObjectDataSource Best Practices? TKelley4591 BOOK: ASP.NET 2.0 Website Programming Problem Design Solution ISBN: 978-0-7645-8464-0 0 July 20th, 2007 02:39 PM
CH5 ObjectDataSource nabeelalkaff BOOK: ASP.NET 2.0 Website Programming Problem Design Solution ISBN: 978-0-7645-8464-0 0 March 8th, 2007 01:19 PM
Formview with ObjectDataSource rturner003 ASP.NET 2.0 Professional 3 November 1st, 2006 06:17 AM
ObjectDataSource and Wildcards pipelineconsulting ASP.NET 2.0 Professional 1 October 19th, 2006 09:08 PM



All times are GMT -4. The time now is 09:00 PM.


Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.