Welcome to Catalyst Blogs Sign in | Join | Help
ASP.NET Dynamic Data Filtering - DynamicFilterRepeater

One of the new features I released with Dynamic Data Filtering 1.10 is the DynamicFilterRepeater control.  This control was added based on requests from several people who have implemented Dynamic Data Filtering in their applications.  The idea is to use the model metadata to generate the set of filtering controls on each page as opposed to using the DynamicFilterForm.  This is a great addition because it allows developers to annotate their model and modify their PageTemplates to get full Dynamic Filtering capabilities throughout the site.

The first step in using the DynamicFilterRepeater is to replace the existing FilterRepeater on either the DynamicData\PageTemplates\List.aspx or DynamicData\PageTemplates\ListDetails.aspx page. 

In this example we will focus on the List.aspx page. On the List.aspx page, the default FilterRepeater controls looks something like:

<asp:FilterRepeater ID="FilterRepeater" runat="server">
    <ItemTemplate>
        <asp:Label runat="server" Text='<%# Eval("DisplayName") %>' AssociatedControlID="DynamicFilter$DropDownList1" />
        <asp:DynamicFilter runat="server" ID="DynamicFilter" OnSelectedIndexChanged="OnFilterSelectedIndexChanged" />
    </ItemTemplate>
    <FooterTemplate><br /><br /></FooterTemplate>
</asp:FilterRepeater>

Delete it!

Next drag the DynamicFilterRepeater from the tool box on to the form. You will get markup that looks like the following:

Tip: I HIGHLY recommend you do this in the designer view.  If you do you will get prompted to create the FilterTemplates directory, if it is not already created.  References to Catalyst.Web.DynamicData and Catalyst.ComponentModel.DataAnnotations will also be added.

<asp:DynamicFilterRepeater ID="DynamicFilterRepeater1" runat="server">
    <HeaderTemplate>
        <div>
            Search</div>
    </HeaderTemplate>
    <ItemTemplate>
        <div>
            <asp:Label ID="Label1" runat="server" Text='<%# Eval("DisplayName") %>'></asp:Label><asp:DynamicFilterControl
                ID="DynamicFilter" runat="server">
            </asp:DynamicFilterControl>
        </div>
    </ItemTemplate>
    <FooterTemplate>
        <div>
            <asp:LinkButton ID="SearchButton" runat="server" CommandName="Search" Text="Search">
            </asp:LinkButton><asp:LinkButton ID="ClearButton" runat="server" CommandName="Clear"
                Text="Clear">
            </asp:LinkButton></div>
    </FooterTemplate>
</asp:DynamicFilterRepeater>

This is the default template for items within the DynamicFilterRepeater and is very similar to the FilterRepeater we just deleted.  You can customize this, but you must, MUST, MUST have one and only one DynamicFilterControl with the ID="DynamicFilter" in the ItemTemplate.  The DynamicFilterRepeater container uses this to create your filtering controls.

After we have the DynamicFilterRepeater control completed, we need to replace the LinqDataSource with a DynamicLinqDataSource. The existing LinqDataSource should look something like this:

<asp:LinqDataSource ID="GridDataSource" runat="server" EnableDelete="true" EnableUpdate="true">
    <WhereParameters>
        <asp:DynamicControlParameter ControlID="FilterRepeater" />
    </WhereParameters>
</asp:LinqDataSource>

Don't delete it.  Switch to the designer view and select your DynamicFilterRepeater and then the Actions pop-up arrow.  This will allow you to select a DataSource.  Select your target datasource, in this case GridDataSource, from the drop down list.  You will see an action called UpgradeData source appear in the Action popup, hit it.  This will automatically change your LinqDataSource to a DynamicLinqDataSource, pretty cool, huh?

Your data source should now look like this (notice the removal of the DynamicControlParameter tag!):

<asp:DynamicLinqDataSource ID="GridDataSource" runat="server" 
    EnableDelete="True" EnableUpdate="True">
</asp:DynamicLinqDataSource>

If you dragged the DynamicFilterRepeater onto the form in DesignView, it will automatically have added a reference to Catalyst.ComponentModel.DataAnnotations, if not you must add a reference.  It should be in the list under the .NET tab, otherwise browse to %PROGRAMFILES%\Dynamic Data Filtering\bin. 

The final step is to modify the metamodel.  Since the samples provided with the installer use the AdventureWorksLT2008 database I am going to annotate the Product class.  This is an example of the Product class and annotations.

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Catalyst.ComponentModel.DataAnnotations;
 
namespace AdventureWorks.BusinessObjects
{
    [System.ComponentModel.DataAnnotations.MetadataType(typeof(ProductMetadata))]
    public partial class Product
    {
        /// <summary>
        /// This is the Metadata for the parent Product class.  It is a private interface to prevent 
        /// consumers from attempting to instantiate it or even see it.
        /// </summary>
        private interface ProductMetadata
        {
            [Filter(FilterMode = FilterControlMode.Contains)]
            string Name { get; set; }
 
            [Filter(FilterMode = FilterControlMode.Contains)]
            [DisplayName("Product Number")]
            string ProductNumber { get; set; }
 
            [Filter(FilterMode = FilterControlMode.Contains)]
            string Color { get; set; }
 
            [Filter(FilterMode = FilterControlMode.Range)]
            [DisplayName("List Price")]
            decimal ListPrice { get; set; }
 
            [Filter(FilterMode = FilterControlMode.Equals)]
            [DisplayName("Product Model")]
            ProductModel ProductModel { get; set; }
 
            [Filter(FilterMode=FilterControlMode.Equals)]
            [DisplayName("Product Category")]
            ProductCategory ProductCategory { get; set; }
 
            [ScaffoldColumn(false)]
            Guid rowguid { get; set; }
 
            [ScaffoldColumn(false)]
            DateTime ModifiedDate { get; set; }
        }
    }
}

One thing to note in this example is that I have made the Metadata class a private nested interface of the Product class.  I have done this to prevent visibility from outside classes and also to prevent any code within the Product class from attempting to instantiate a instance of that type.  While giving a presentation last week, Scott Seely asked if this was possible, we tried it on the stop and it worked like a charm. 

Now run the solution and you should have FilterControls defined for List.aspx page template.

Posted: Wednesday, October 01, 2008 10:06 AM by jheyse
Filed under: ,

Comments

tigermoth said:

Josh, your DDFiltering 1.10 seems awesome! Thanks for making it available. I'm trying to install it, but your installer is notifying me that I must have the Toolbox Controls Installer to continue.

I only have Visual Web Developer 2008 Express and being somewhat new to this environment, I don't quite know how to proceed. Could you please point me in the right direction?

Thanks very much!

TM

# October 1, 2008 7:09 PM

Rjbullock said:

This is awesome idea, but i can't see the search from... Any ideas? Followed all of your steps and I don't get an error, just don't see the search fields.

# October 2, 2008 10:50 AM

Rjbullock said:

John, I figured a few things out, but now I'm getting this error:

Could not load type '$rootnamespace$.Text_Contains'

It was weird... When I removed the Namespace from my class, my normal annotations worked, but when I added back the filter annotations, it broke...

# October 2, 2008 12:09 PM

Rjbullock said:

Here's the complete error:

Line 1:  <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Text_Contains.ascx.cs" Inherits="$rootnamespace$.Text_Contains" %>

Line 2:  <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

# October 2, 2008 12:32 PM

jheyse said:

tigermoth,

I have added an installer to the Codeplex project called "Dynamic Data Filtering Installer w/o Toolbox Insaller".  Try using that.  If it installs you will have to manually add the controls to the Toolbox.  This is done by right clicking on the toolbox and select "Choose Items", then select the 4 controls in the Catalyst.Web.DynamicData (1.1.0.0) Assembly.  It is easiest if you sort by Assembly and scroll to the top.

Josh

# October 2, 2008 2:24 PM

jheyse said:

Rjbullock,

Can you please post any issues to the CodePlex discussion forum.  It's best if you can attach or paste your aspx page.

Josh

# October 2, 2008 2:25 PM

tigermoth said:

>>I have added an installer to the Codeplex project called "Dynamic Data Filtering Installer w/o Toolbox Insaller".

That did it, thanks a lot!

# October 2, 2008 10:36 PM

whatThe said:

I get an error for very filter template control starting with:

"Could not load type '$rootnamespace$.Integer'."

It would be wonderful if publishers of controls or extension libraries would test their product before releasing them.

# October 15, 2008 5:33 PM

Soraz said:

Regarding the $rootnamespace$ problem, i had the same problem.

I fixed it by doing search/replace in all files for $rootnamespace$ with DynamicData.FilterTemplates.

This still left me with "Unable to load type Text_Contains" (for all types).

This was solved by Replacing CodeBehind="foofile.ascx" with CodeFile="foofile.ascx" in all the generated files.

I use VS2008 SP1 btw.

# October 16, 2008 2:02 AM

Luca said:

Hi,

i've got the same problem of Rjbullock. i followed all the guidelines given in this post, i compiled my website and the list page doesn't show any search field...

# October 28, 2008 6:15 AM

Shimon said:

Hi,

When I try to get  List.aspx of of any table I get "Missing DataSource" Error!!

The Code :

  <asp:DynamicFilterRepeater ID="DynamicFilterRepeater1" runat="server">

               <HeaderTemplate>

                   <div>

                       Search</div>

               </HeaderTemplate>

               <ItemTemplate>

                   <div>

                       <asp:Label ID="Label1" runat="server" Text='<%# Eval("DisplayName") %>'></asp:Label><asp:DynamicFilterControl

                           ID="DynamicFilter" runat="server">

                       </asp:DynamicFilterControl>

                   </div>

               </ItemTemplate>

               <FooterTemplate>

                   <div>

                       <asp:LinkButton ID="SearchButton" runat="server" CommandName="Search" Text="Search">

                       </asp:LinkButton><asp:LinkButton ID="ClearButton" runat="server" CommandName="Clear"

                           Text="Clear">

                       </asp:LinkButton></div>

               </FooterTemplate>

           </asp:DynamicFilterRepeater>

           <asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource" AllowPaging="True"

               AllowSorting="True" CssClass="gridview">

               <Columns>

                   <asp:TemplateField>

                       <ItemTemplate>

                           <asp:HyperLink ID="EditHyperLink" runat="server" NavigateUrl='<%# table.GetActionPath(PageAction.Edit, GetDataItem()) %>'

                               Text="ערוך" />&nbsp;<asp:LinkButton ID="DeleteLinkButton" runat="server" CommandName="Delete"

                                   CausesValidation="false" Text="מחק" OnClientClick='return confirm("Are you sure you want to delete this item?");' />&nbsp;<asp:HyperLink

                                       ID="DetailsHyperLink" runat="server" NavigateUrl='<%# table.GetActionPath(PageAction.Details, GetDataItem()) %>'

                                       Text="פרטים" />

                       </ItemTemplate>

                   </asp:TemplateField>

               </Columns>

               <PagerStyle CssClass="footer" />

               <PagerTemplate>

                   <asp:GridViewPager runat="server" />

               </PagerTemplate>

               <EmptyDataTemplate>

                   אין נתונים.

               </EmptyDataTemplate>

           </asp:GridView>

           <asp:DynamicLinqDataSource ID="GridDataSource" runat="server" EnableDelete="True"

               EnableUpdate="True">

           </asp:DynamicLinqDataSource>

# October 31, 2008 2:32 AM

jheyse said:

Shimon,

Your DynmaicFilterRepeater is missing a reference to the DynamicLinqDataSource.

<asp:DynamicFilterRepeater ID="DynamicFilterRepeater1" runat="server" DataSourceID="GridDataSource" >

Hope this helps!

# November 1, 2008 4:33 PM

Martin said:

hi, i got a problem of my dynamicFilter always being a textbox, where i wan it to be a dropdownlist.

after reading the forum + seeing some samples, i think the control should be controlled by FilterUserControl.ascx. However, i check that control, i am having a dropdownlist inside that control.

<%@ Control Language="C#" CodeBehind="FilterUserControl.ascx.cs" Inherits="BudgetModule.FilterUserControl" %>

<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" EnableViewState="true" CssClass="droplist">

   <asp:ListItem Text="All" Value="" />

</asp:DropDownList>

lets look at my aspx:

<asp:DynamicFilterRepeater ID="DynamicFilterRepeater" runat="server" DataSourceID="GridDataSource">          

               <HeaderTemplate>

                   <table>

                       <tr>

                           <td colspan="2">Search</th>

                       </tr>

               </HeaderTemplate>

               <ItemTemplate>

                   <tr>

                       <td><asp:Label ID="Label1" runat="server" Text='<%# Eval("DisplayName") %>' />

                       </td>

                       <td><asp:DynamicFilterControl runat="server" ID="DynamicFilter"   ></asp:DynamicFilterControl>

                       </td>

                   </tr>

               </ItemTemplate>

               <FooterTemplate>

                       <tr>

                           <td colspan="2" align="center">

                               <asp:LinkButton ID="LinkButton1" runat="server" Text="Search" CommandName="Search" />

                               <asp:LinkButton ID="LinkButton2" runat="server" Text="Clear" CommandName="Clear" />

                           </td>

                       </tr>

                   </table>

               </FooterTemplate>

           </asp:DynamicFilterRepeater>

i was wondering do i need have some sort of AssociatedControlID method called on the aspx inorder to make the dynamicFilterControl into a drop down list, instead of currently a textbox?

I am very confused over this matter, hope someone could give me a gd suggestion in how to fix this problem. or at least tell me am i on the right track regarding change from textbox to drop down list. thanks

# November 6, 2008 1:39 AM

jheyse said:

Martin,

To change the type of Filter Control used, you have to attribute your metamodel.  Currently only a DropDownList will be used if the column is a foreign key.  What is the column you are trying to filter on?

# November 6, 2008 9:53 AM

Ulli said:

I've got the same problem:

"Could not load type '$rootnamespace$.Integer'."

But I couldn't replace it with my rootnamespace, because I've just got a VS Website and no VS Project, therefore cannot set a rootnamespace.

Changing it to Inherits="_Integer" also throws an error.

# November 7, 2008 11:02 AM

Lyndon said:

Hi- I have tried out your dynamic datafiltering controls and steps above, but in VB instead of C#.

All the steps you mention above work until I get to the last step of modifying the metamodel.

in vb I have done the following

Imports System.Web.DynamicData

Imports System.ComponentModel

Imports System.ComponentModel.DataAnnotations

Imports Catalyst.ComponentModel.DataAnnotations

Namespace HRSMDyn

   <System.ComponentModel.DataAnnotations.MetadataType(GetType(ServiceRequestMetadata))> _

Partial Public Class ServiceRequest

Private Interface ServiceRequestMetadata

Private _RequestHeading As String

<Filter(Filtermode :=FilterControlMode.Contains)>  _

<DisplayName("Request Heading")> _

          Property RequestHeading() As String  

End Interface

End Class

End Namespace

It barfs on

<System.ComponentModel.DataAnnotations.MetadataType(GetType(ServiceRequestMetadata))> _

It doesnt seem to be able to find/understand the ServiceRequestMetaData- saying that it is not defined. Any thoughts? (probably a dumb oversight on my part)

Thanks

# November 11, 2008 6:52 PM

jheyse said:

Lyndon,

Does fully qualifying it ServiceRequest.ServiceRequestMetadata work?

Josh

# November 14, 2008 9:24 AM

Rudolf Terppe said:

hi josh

I've got the same problem like Ulli

"Could not load type '$rootnamespace$.Integer'."

But I couldn't replace it with my rootnamespace, because I've just got a VS Website and no VS Project, therefore cannot set a rootnamespace.

Changing it to Inherits="_Integer" also throws an error.

I also tried !!

...

I have added an installer to the Codeplex project called "Dynamic Data Filtering Installer w/o Toolbox Insaller".  Try using that.  If it installs you will have to manually add the controls to the Toolbox.  This is done by right clicking on the toolbox and select "Choose Items", then select the 4 controls in the Catalyst.Web.DynamicData (1.1.0.0) Assembly.  It is easiest if you sort by Assembly and scroll to the top.

Is there any new idea for this problem?

rudolf

# November 16, 2008 9:39 AM

Chris Prodeus said:

Hey Josh!

I've followed the steps.

First off, the Product class example you've provided here is different then the c# sample class from the download on codeplex. So that's a bit confusing, but hopefully I managed to have it setup correctly. Can I remove the Metadata folder and Product class within it?

Here's my problem, like a few others have mentioned, my code compiles just fine, but my list.aspx page loads the DynamicFilterReapter without the filter controls. The word "search" shows up and so do the hyperlinks, but that's it.

What am I missing?  I'm sure it's something obvious. FYI - In order for me to get it to compile I had to change the $rootnamespace$ throughout the application, as well as change codebehind= to codefile= in all filter control pages.

Please help, I need to get this working ASAP!!!!

# December 4, 2008 8:52 AM

jheyse said:

Chris,

I responded to you the CodePlex site, please check there.

Josh

# December 12, 2008 9:57 AM

Mr. Snor said:

Thanks for the tool; saves me from having to do some work. :{)

I think some people are getting the $rootnamespace$ error because your FilterTemplate generator targets web applications and not file-based websites. I had the same problem and fixed it by modifying the files to work with file-based websites (i.e. removing the namespace and changing "codebehind" to "codefile".)

Mr. Snor

:{

# December 18, 2008 5:43 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS