How to extract extra data from LinqDataSource? - asp.net

I have a simple wizard generated query in a LinqDataSource like this:
<asp:LinqDataSource ID="EvaluationsData" runat="server" ContextTypeName="Bonus.Models.BonusDataContext"
Select="new (Id, Name, Coverage)" TableName="BM_Evaluations"
</asp:LinqDataSource>
I assign this data source to a DropDownList, using Id and Name as the DataValueField and DataTextField respectively. But when I selected a option, I want to keep the Coverage too, extracting it from the data source and storage in a HiddenField. It's a way to do this without making another query to the database?
Thanks.

To do this, you'll need to intercept the returned list of items from the data source and then manually assign Coverage to the items in the drop-down's items.
Here's your markup
<asp:LinqDataSource ID="EvaluationsData" runat="server"
ContextTypeName="Bonus.Models.BonusDataContext"
Select="new (Id, Name, Coverage)" TableName="BM_Evaluations"
onselected="EvaluationsData_Selected">
</asp:LinqDataSource>
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="EvaluationsData" DataValueField="Id" DataTextField="Name"
ondatabound="DropDownList1_DataBound">
</asp:DropDownList>
Here's your code
List<object> evaluations;
protected void EvaluationsData_Selected(object sender, LinqDataSourceStatusEventArgs e)
{
evaluations = new List<object>(e.Result as IEnumerable<object>);
}
protected void DropDownList1_DataBound(object sender, EventArgs e)
{
foreach (ListItem item in DropDownList1.Items)
{
var eval = evaluations.Where(a => a.Id == item.Value).FirstOrDefault();
if (eval != null)
{
item.Attributes.Add("Coverage", eval.Coverage);
}
}
}

Related

Simultaneously deleting a file from a DataBase and a Folder using a LinkButton or Gridview_RowDeleting method

HELP! Is it achievable to use LinkButton or Gridview_RowDeleting method to simultaneously delete a file from a DataBase and from a Folder? Below is my code using a LinkButton:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID = "lnkDelete" Text = "Delete" OnClientClick="return confirm('Are you sure you want to delete this record?');" CommandArgument = '<%# DataBinder.Eval(Container.DataItem,"ID") %>' runat = "server" OnClick = "DeleteFile" />
</ItemTemplate>
</asp:TemplateField>
Code Behind:
protected void grdProducts_RowEditing(object sender, GridViewEditEventArgs e)
{
//Get seleted row
GridViewRow row = grdProducts.Rows[e.NewEditIndex];
//Get Id of selected product
int rowId = Convert.ToInt32(row.Cells[1].Text);
//Redirect user to Manage Products along with the selected rowId
Response.Redirect("~/Pages/Management/ManageProducts.aspx?id=" + rowId);
}
protected void DeleteFile(object sender, EventArgs e)
{
string filePath = (sender as LinkButton).CommandArgument;
File.Delete(filePath);
Response.Redirect(Request.Url.AbsoluteUri);
}
PL: I have an existing gridview and a datasource for my table.
Thank you all for your contribution. I later got the answer to this. I will like to share it with all. Just enable OnRowDeleting in your Gridview properties then use the code behind below.
protected void grdProducts_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
Image oImg = grdProducts.Rows[e.RowIndex].FindControl("ImageFile") as Image;
if (oImg != null)
{
string sUrl = oImg.ImageUrl;
File.Delete(Server.MapPath(sUrl));
grdProducts.DataBind();
}
}
}
Finally: put this TemplateField on your aspx page.
<asp:TemplateField>
<ItemTemplate>
<asp:Image ID="ImageFile" runat="server" ImageUrl='<%# Bind("Image", "Images/Products/{0}")%>' AlternateText="Picture unavailable" style="width:50px; height:40px" />
</ItemTemplate>
</asp:TemplateField>

filter Records using Dropdownlist in a Datalist and Datatable

Here I need to filter Data using Dropdownlist in Datalist
i Have more than 1000 Records everything its stored with their Category Name....
its in String(A,B,C,D......to Z) and
i have some values in dropdownlist(1.2,3,5,10,all) here how i need filter the data in datalist means by dropdownindex changed to 1 in that case it show only the record which available in alphabet A,
if index changed 2 it Should show the records od A & B ......As so on...by indexing to all it should show all the Record in the database....
Set the AutoPostBack property of DropDownlist to true and use the SelectedIndexChanged event..
<asp:DropDownList ID="DDwn1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="DDwn1_SelectedIndexChanged">
<asp:ListItem Text="Sort ascending" Value="ASC"></asp:ListItem>
<asp:ListItem Text="Sort descending" Value="DESC"></asp:ListItem>
</asp:DropDownList>
private void showData(string sortDirection)
{
//bind to data list
}
protected void DDwn1_SelectedIndexChanged(object sender, EventArgs e)
{
showData(DDwn1.SelectedValue);
}

Why do I have to click a button twice in an ASP.NET repeater to get the command to fire?

I have an ASP.NET page with the following 3 main areas:
1 - list of checkboxes on the left for fitlering results
2 - Repeater that displays the matching results in the middle (with a button for each item)
3 - Repeater that displays the selected items on the right
On initial page load the page will show the data bound checkboxes and will show all results (since nothing has been checked in the filters). As the user checks or unchecks the checkboxes, the page will reload and the matching results will change. So far this part works great.
In the Results Repeater, each item has a Button. When the user clicks the button for an item in the Results the idea is that the item will get added to the Selected Repeater on the right. What is happening is that after I check or uncheck filter checkboxes - the first time that I then try and click on the buttons in the Results repeater, nothing happens. The page just reloads. Then if I click the button a second time, the Repeater Command will fire and the item will get added to the Repeater on the right hand side. Then, as long as I don't change any of the checkboxes I can click on one of the command buttons and it will work right away. But if I check one of the checkboxes in the filters area (which causes the Results to get re-bound) then I have to click one of the buttons twice to get it to fire.
I have a sense that this has something to do with ViewState but I have no idea. Does anyone know why this would be happening?
Below is my code for both the ASPX page and the code behind.
ASPX Code:
<h3>Filters</h3>
<asp:Repeater ID="rptTechnologies" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
<HeaderTemplate><h4>Technology</h4></HeaderTemplate>
<ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>
<asp:Repeater ID="rptVerticals" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
<HeaderTemplate><h4>Vertical</h4></HeaderTemplate>
<ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>
<asp:Repeater ID="rptIndustries" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
<HeaderTemplate><h4>Industry</h4></HeaderTemplate>
<ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>
<asp:Repeater ID="rptSolutions" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
<HeaderTemplate><h4>Solution</h4></HeaderTemplate>
<ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>
<h3>Results</h3>
<asp:Repeater ID="rptMatchingSlides" runat="server" OnItemDataBound="rptMatchingSlides_ItemDataBound" OnItemCommand="rptMatchingSlides_Command">
<ItemTemplate>
<h4><asp:Literal ID="litName" runat="server"></asp:Literal></h4>
<asp:Button ID="btnSelect" runat="server" Text="Select" CommandName="Select" />
</ItemTemplate>
<SeparatorTemplate><hr /></SeparatorTemplate>
</asp:Repeater>
<h3>Selected</h3>
<asp:Repeater ID="rptSelectedSlides" runat="server" OnItemDataBound="rptSelectedSlides_ItemDataBound">
<ItemTemplate>
<h4><asp:Literal ID="litName" runat="server"></asp:Literal></h4>
</ItemTemplate>
<SeparatorTemplate><hr /></SeparatorTemplate>
</asp:Repeater>
Here is the code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.BindData();
}
}
public List<string> SelectedSlides
{
get
{
if (Session["SelectedIDs"] != null)
{
string[] _ids = Session["SelectedIDs"].ToString().Split(new char[] { '|' });
List<String> _retVal = new List<string>();
foreach (string _id in _ids)
{
_retVal.Add(_id);
}
return _retVal;
}
else
{
return new List<string>();
}
}
set
{
//Set the session value
string _val = "";
foreach (string _id in value)
{
if (_val == "")
{
_val = _id;
}
else
{
_val += "|" + _id;
}
}
Session["SelectedIDs"] = _val;
}
}
protected void BindData()
{
//Filters
rptTechnologies.DataSource = Repository.GetTaxonomyItems();
rptTechnologies.DataBind();
rptVerticals.DataSource = Repository.GetTaxonomyItems();
rptVerticals.DataBind();
rptIndustries.DataSource = Repository.GetTaxonomyItems();
rptIndustries.DataBind();
rptSolutions.DataSource = Repository.GetTaxonomyItems();
rptSolutions.DataBind();
this.BindMatchingSlides();
}
protected void BindMatchingSlides()
{
...build list of ids from checkboxes...
rptMatchingSlides.DataSource = Repository.GetMatchingSlides(_selectedIDs);
rptMatchingSlides.DataBind();
}
protected void BindSelectedSlides()
{
if (this.SelectedSlides.Count > 0)
{
rptSelectedSlides.DataSource = this.SelectedSlides;
rptSelectedSlides.DataBind();
}
else
{
divSelectedSlides.Visible = false;
}
}
protected void rptMatchingSlides_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Literal _litName = (Literal)e.Item.FindControl("litName");
Button _btnSelect = (Button)e.Item.FindControl("btnSelect");
_litName.Text = ...set name here...
_btnSelect.CommandArgument = ...use unique ID of item from database...
_btnSelect.ID = "btnSelect_" + e.Item.ItemIndex;
}
}
protected void rptMatchingSlides_Command(object sender, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Select")
{
Item _slide = ...get data from database based on Command Argument...
if (_slide != null)
{
List<string> _selectedSlides = this.SelectedSlides;
_selectedSlides.Add(_slide.ID.ToString());
this.SelectedSlides = _selectedSlides;
}
this.BindSelectedSlides();
}
}
Thanks to Jeremy - removing the line of code where I was setting the ID fixed it. Doh! Somewhere else I had read that you needed to set a unique value for the IDs of the buttons in a repeater. So that must have been the culprit. Thanks to Jeremy.

ASP.Net: drop down list and data source created dynamically

I have about 10 drop down list controls that get populated. Instead of copying/pasting and modifying a few fields on each, I would like to create them programmatically. Can this be done?
Here is what one of them looks like. I would like to programmatically add 10 dropdownlist controls and their respective SqlDataSource controls.
<asp:SqlDataSource ID = "ddlDAGender" runat=server
ConnectionString="<%$ ConnectionStrings:test1ConnectionString %>"
SelectCommand = "select GenderID,Gender from mylookupGender"
>
</asp:SqlDataSource>
<asp:Label ID="Label3" runat="server" Text="Gender"></asp:Label>
<asp:DropDownList ID="ddlGender" runat="server"
DataSourceid="ddlDAGender"
DataTextField="Gender" DataValueField="GenderID"
>
</asp:DropDownList>
You can always create your controls dynamically. In this case though, if all your drop down lists are different, I'm not sure it's saving you anything, since you'll still have to assign them individual ID's and datasources.
Here's what the code might look like:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindDropDownLists();
}
}
protected void Page_Init(object sender, EventArgs e)
{
SqlDataSource sqlDS = new SqlDataSource();
sqlDS.ConnectionString = ConfigurationManager.ConnectionStrings[0].ToString();
sqlDS.SelectCommand = "select GenderID,Gender from mylookupGender";
form1.Controls.Add(sqlDS);
DropDownList ddl = new DropDownList();
ddl.ID = "dddlGender";
ddl.DataSource = sqlDS;
ddl.DataTextField = "Gender";
ddl.DataValueField = "GenderID";
form1.Controls.Add(ddl);
// ... Repeat above code 9 times or put in a for loop if they're all the same...
}
private void BindDropDownLists()
{
foreach (Control ctl in form1.Controls)
{
if (ctl is DropDownList)
{
(ctl as DropDownList).DataBind();
}
}
}

DropDownList with LinqDataSource and an empty option

Is there some elegant way to add an empty option to a DropDownList bound with a LinqDataSource?
Here's how to add a value at the top of the list. It can be an empty string, or some text.
<asp:DropDownList ID="categories" runat="server" AppendDataBoundItems="True" AutoPostBack="True" DataSourceID="categoriesDataSource" DataTextField="CategoryName" DataValueField="CategoryID" EnableViewState="False">
<asp:ListItem Value="-1">
-- Choose a Category --
</asp:ListItem>
</asp:DropDownList>
Be sure to set the DropDownList's AppendDataBoundItems=True.
Markup:
<asp:DropDownList ID="ddlQualQuestion" runat="server" DataSourceID="sdsQualQuestion" DataTextField="ShortQuestionText" DataValueField="QualificationQuestionKey" AutoPostBack="true" OnSelectedIndexChanged="ddlQualQuestion_SelectedIndexChanged" OnDataBound="ddlQualQuestion_DataBound" />;
Code behind:
protected void ddlQualQuestion_DataBound(object sender, EventArgs e)
{
ddlQualQuestion.Items.Insert(0, new ListItem("", "0"));
}
Taking the solution DOK provided:
<asp:DropDownList ID="categories" runat="server" AppendDataBoundItems="True" AutoPostBack="True" DataSourceID="categoriesDataSource" DataTextField="CategoryName" DataValueField="CategoryID" EnableViewState="False">
<asp:ListItem Value="-1">
-- Choose a Category --
</asp:ListItem>
</asp:DropDownList>
Addtionally, if you don't want to force the user to make a selection you can add a method to the LinqDataSource of your GridView:
OnSelecting="myGridview_Selecting"
Add code behind like this:
protected void myGridview_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
if (categories.SelectedValue == "-1")
{
e.WhereParameters.Remove("CategoryID");
}
}
I'd provide an extension method on IEnumerable<string> that prepended an item to the beginning of the list:
public static IEnumerable<string> Prepend(this IEnumerable<string> data, string item)
{
return new string[] { item == null ? string.Empty : item }.Union(data);
}
Its sort of linq-y, as it uses the linq extension method Union. Its a little cleaner than doing this:
var result = new string[]{string.Empty}.Union(from x in data select x.ToString());

Resources