Question

I have an ObjectDataSource for my FormView (Students) and another ObjectDatSource for the DropDownList (Name) within the FormView. If the DropDownList's source does not contain a name value matching the formview's source, I would like to display "Not available". Currently I have this code, which works if the datasource returns a NULL value. How can I change this to display "Not Available" when the FormView name value is not in the DropDownList's databound list?

<asp:FormView ID="Students" runat="server" DataSourceID="Students_DataSource">
    <ItemTemplate>
        <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name") %>' />
    </ItemTemplate>
    <EditTemplate>
        <asp:DropDownList ID="ddlName" runat="server" 
        SelectedValue='<%# If(Eval("Name") IsNot Nothing, Eval("Name"), "Not Available") %>' 
                    DataSourceID="fvAllNames" runat="server" DataTextField="Name" DataValueField="Name" />        
    </EditTemplate>
</asp:FormView>
Was it helpful?

Solution

public class MyItem
{
    public string Name { get; set; }
    public int UserId { get; set; }
}

public void MethodThatLoadsMyData
{
    var originalListData = MethodThatFetchesMyData(45);
    myDropDownList.DataSource = MethodThatBumpsTwoItemDatasources(myOuterList, originalListData);
    myDropDownList.DataBind();
}

public void MethodThatBumpsTwoItemDatasources(List<MyItem> outerList, List<MyItem> dropdownList)
{
    /*This modifies the original result set from the database that you were going
    to use to populate your dropdown list. It compares the outer list (whatever that is)
    with the result set, and adds items called "Not Available" when there is an item in the
    outer list that doesn't exist in the dropdownlist */

    var result = new List<Item>();
    foreach (var item in listA)
    {
        var matched = false;
        foreach (var itemB in listB.Where(itemB => itemB.Id == item.Id))
        {
            matched = true;
            result.Add(item);
        }
        if (!matched)
        {
            result.Add(new Item
            {
                Name = "Not Available",
                Id = 0
            });
        }
        matched = false; 
    }
    return result;
}

public List<MyItem> MethodThatFetchesMyData(int myParameter)
{
    //gets my data from the database and builds dto objects
    var sql = "my_stored_procedure_or_sql";
    var list = new List<MyItems>();
    using(var conn = new SqlConnection(myConnectionString))
    {
        using(var comm = new SqlCommand(sql, conn))
        {
            //do your normal client setup here (sql type, parameters, etc//
            var parameters = SqlParameter[1];
            parameters[0] = new SqlParameter("@ParameterName", DbType.Int);
            parameters[0].Value = myParameter;
            comm.Parameters = parameters;
            comm.CommandType = CommandType.StoredProcedure;
            conn.Open();
            using(var rdr = comm.ExecuteReader())
            {
                while(rdr.Read())
                {
                    list.Add(
                        new MyItem{
                            Name = rdr["NameColumn"].ToString(),
                            UserId = rdr["ID"]
                        });
                }
                return list;
            }
        }
    }
}

In your databound controls, you can get at the new values in the itemtemplate with your typical

<%#Eval("Name") %> <%#Eval("UserId") %>

What I'm actually doing here is binding the controls to a list of actual objects instead of the datatable that is constructed with the datasource control. By doing that, I can do whatever I need to do with those lists before binding it to the control. In this case, I bump the two lists together and add items for those that do not exist in one list but exist in the other. Not sure if this is exactly what you needed, but this should be enough to give you some ideas.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top