Binding [NavigationData] to a selected item in a DropDownList

May 29, 2013 at 11:55 PM
Edited May 30, 2013 at 12:03 AM
I have a drop down list which is bound to a Controller Method named GetItemTypes.
public List<KeyValuePair<string, string>> GetItemTypes() { ... }

<asp:DropDownList runat="server" ID="ui_ddlItemTypes" AutoPostBack="true" OnCallingDataMethods="ui_ddlIncidentLGA_CallingDataMethods" SelectMethod="GetItemTypes" DataValueField="Key" DataTextField="Value"></asp:DropDownList>
Historically this has called an event on SelectedIndexChanged which filters a GridView. However I am now trying to filter the following GridView which uses the Controller method GetItems:
public List<ItemViewModel> GetItems([NavigationData] string itemType) { ... }

<asp:GridView runat="server" ID="ui_gvwItems" OnCallingDataMethods="ui_gvwItems_CallingDataMethods" ItemType="ItemViewModel" SelectMethod="GetItems">
How do I pass in the selected Value from the DropDownList to the [NavigationData] of the Controller method GetItems?

I think I need a NavighationDataSource as follows, but I am not sure where to place the Bind("[itemType]") on the DropDownList:
<cc1:NavigationDataSource ID="ui_navigationDataSource" runat="server">
    <SelectParameters>
        <cc1:NavigationDataParameter Name="itemType" />
    </SelectParameters>
</cc1:NavigationDataSource>
I tried to do SelectedValue='<%# Bind("[itemType]") %>' but I get an Exception:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
May 30, 2013 at 12:17 AM
Edited May 30, 2013 at 12:36 AM
OK - I think the problem is that the Bind(..) syntax needs to be in the context of a Bound control (e.g. FormView).

After adding this to a FormView and setting the DataSourceID of the FormView it appears to be working.

However, How do I use the value of the selected item to filter the SelectMethod of the GridView?
Coordinator
May 30, 2013 at 7:34 PM
Edited May 30, 2013 at 10:38 PM
Now Web Forms 4.5 Data Binding has landed I don't use NavigationDataSources any more. Instead we can create an ItemType object to hold the DropDown selection:
public class ItemType
{
    public string Key
    {
        get;
        set;
    }
}
Then wrap the DropDownList inside a FormView that has a SelectMethod and UpdateMethod:
<asp:FormView ID="ui_fvwItems" runat="server" DefaultMode="Edit" ItemType="ItemType" SelectMethod="GetItemType" UpdateMethod="SetItemType" OnCallingDataMethods="ui_fvwItems_CallingDataMethods">
    <EditItemTemplate> 
        <asp:DropDownList runat="server" ID="ui_ddlItemTypes" SelectedValue='<%# BindItem.Key %>' AutoPostBack="true" OnCallingDataMethods="ui_ddlIncidentLGA_CallingDataMethods" SelectMethod="GetItemTypes" DataValueField="Key" DataTextField="Value"></asp:DropDownList>
    </EditItemTemplate>
</asp:FormView>
The GetItemType Select method returns an ItemType set from StateContext data:
public ItemType GetItemType()
{
    return new ItemType() { Key = StateContext.Bag.itemType };
}
And the SetItemType Update method takes the ItemType passed in and sets it into StateContext data:
public void SetItemType(ItemType itemType)
{
    StateContext.Bag.itemType = itemType.Key;
}
Then when SetItemType is called the itemType in StateContext changes and GetItems is automatically called with this new value (because of the NavigationData attribute) and the GridView is filtered. Hey presto!

But there's a small catch. When the DropDownList changes the SetItemType method isn't called, even though AutoPostBack is true, because the FormView needs an Update command to be raised and only Buttons can raise commands. Adding a SelectedIndexChanged event to the DropDownList and updating the FormView manually does the trick:
protected void ui_ddlItemTypes_SelectedIndexChanged(object sender, EventArgs e)
{
    ui_fvwItems.UpdateItem(false);
}
Although we've introduced the SelectedIndexChanged event that you were trying to get rid of its job is quite a bit simpler now because the Controller method contains the filtering logic.
Coordinator
Jun 3, 2013 at 7:59 PM
How're you getting on?

Thanks for your question, it got me thinking. I've just checked in some code that makes it much easier to filter a grid with an AutoPostBack DropDownList. There's no need for a FormView nor any codebehind. You can do it by just using NavigationData markup against the OnSelectedIndexChanged event:
<asp:DropDownList runat="server" ID="ui_ddlItemTypes" AutoPostBack="true" OnCallingDataMethods="ui_ddlIncidentLGA_CallingDataMethods" SelectMethod="GetItemTypes" DataValueField="Key" DataTextField="Value" OnSelectedIndexChanged="{NavigationData itemType}"></asp:DropDownList>
When the drop down changes the itemType in StateContext changes, then the GetItems is automatically called and the GridView filtered.

This code isn't released yet but you can download the latest source code or I could send you the dll? To use NavigationData markup syntax make sure you register the NavigationDataControlBuilderInterceptor in your Web.config:
<compilation debug="true" targetFramework="4.5" controlBuilderInterceptorType="Navigation.NavigationDataControlBuilderInterceptor, Navigation">
Jun 5, 2013 at 12:58 AM
Thanks Graham. This looks like exactly what I need!

I am going well. I have a couple of questions, but I will post these as separate threads.

Thanks again!
Jun 5, 2013 at 3:00 AM
Got it working :-) Thanks!