Passing two values through CommandArgument and splitting it - c#

I'm using the commandArgument property of the LinkButton ( Which is wrapped inside a repeater ) to pass two values -as one string- to a second repeater then I try to split them into two values, So I could use them as parameters in my ADO.NET Code (SqlCommand Parameters)....after testing my queries don't return any results but If I passed fixed values for the parameter or change the source of the parameter (just for test from a textbox or querystring or something) I get my results, so I think the problem is in splitting.
I Conduct some arugment values from the ArgumentCommand property of the LinkButton -which is wrapped inside a repeater:
<ItemTemplate>
<asp:LinkButton id="sort_lnkbtn" Text='<%# Eval("value")%>'
CommandArgument='<%#string.Format("{0}|{1}",Eval("arrange_by_id"),Eval("value"))%>' runat="server">
</asp:LinkButton>
</ItemTemplate>
Then I receive these values and cut them into two pieces of information:
string sortByAndArrangeBy = (e.CommandArgument).ToString();
char[] separator = { '|' };
string[] sortByAndArrangeByArray = sortByAndArrangeBy.Split(separator);
Now the ado.net code uses this values as a
using (SqlConnection cn1 = new SqlConnection(ConfigurationManager.ConnectionStrings["testConnectionString"].ConnectionString))
{
using (SqlCommand cm1 = new SqlCommand("SELECT [name] FROM brands WHERE (name like #SearchString + '%' )", cn1))
{
cm1.Parameters.Add("#SearchString", System.Data.SqlDbType.Char);
cm1.Parameters["#SearchString"].Value = sortByAndArrangeByArray[1];
cn1.Open();
using (SqlDataReader dr1 = cm1.ExecuteReader())
{
List_rpt.DataSource = dr1;
List_rpt.DataBind();
}
}
}

Here is a simple solution:
Wrap your item template for the repeater in a control. The control will have the same markup as your item template without the bindings:
Control Markup:
<div>
<asp:LinkButton ID="LnkBtnSort" runat="server" Text="Sort" OnClick="LnkBtnSort_Clicked"/>
</div>
Control Code:
public class SomeControl
{
public event EventHandler Click;
public string ArrangeById
{
set { ViewState["byid"] = value; }
get { return ViewState["byid"].ToString(); }
}
public string Value
{
set { ViewState["val"] = value; }
get { return ViewState["val"].ToString(); }
}
protected void LnkBtnSort_Clicked(object sender, EventArgs e)
{
if( Click != null )
{
this.Click(this, EventArgs.Empty);
}
}
}
So now in the repeater all you have to do is bind an instance of that control to the Container.DataItem:
<ItemTemplate>
<ctrl:SomeControl
ID="someControl"
runat="server"
OnClick="SomeControl_Clicked"
ArrangeById='<%# Eval("arrange_by_id") %>'
Value='<%# Eval("value") %>' />
</ItemTemplate>
The page/control that has the repeater will have one simple method:
protected void SomeControl_Clicked(object sender, EventArgs e)
{
//Here cast the sender to the type of control you made:
SomeControl ctrl = (SomeControl)sender;
string byId = ctrl.ArrangeById;
string val = ctrl.Value;
}
Note: this code may not be 100% correct but it illustrates the point. The flow is simple - the control binds its public properties to whatever you need to bind. When the link is clicked (inside your control) the control doesn't propagate this event to the page. Instead it fires its own event (Click) thus sending a signal to the page that an event occured. however by doing so, it changes the source of the event to itself instead of the actual link button. The page handles the event and everyone is happy.
This way you don't have to care what the CommandArgument is... If this comes up empty, it means that either your data source is empty... or something else happened in the code.

Related

Update and delete data in database using datagridview

try
{
TblProduct product = new TblProduct();
product.Description = textBox1.Text;
product.Price = decimal.Parse(textBox2.Text);
product.Image = imagedata;
product.ProductType = (int)comboBox1.SelectedValue;
msd.AddToTblProducts(product);
msd.SaveChanges();
Msgbox mg = new Msgbox();
mg.ShowDialog();
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
I want to delete and update data using datagridview. How do I do this?
To help you get started, inside of your Grid you would attach a button. Since I'm not sure if your utilizing Model View Controller, Web Forms, or another aspect I'll default to Web Forms. For instance:
<asp:LinkButton id='btnEdit-<%# Eval("Id") %>' runat="server"
CommandName="Delete"
CommandArgument='<%# Eval("Id")'
OnClick="btnDelete_Click"
Tooltip='<%# String.Format("Delete Record: {0}", Eval("Id")) %>' />
So the following button provides an argument name, when we push to code behind the CommandArgument value will now be accessible based on the Grid Id. That is what the Eval is exposing for us.
On the code behind, you would have the following:
protected void btnDelete_Click(object sender, EventArgs e)
{
var id = ((LinkButton)sender).CommandArgument as int?;
}
Inside the brackets the following occurs:
Instantiation
Retrieve the value in the CommandArgument
Casting as an int?
The instantiation is important to access the control, the CommandArgument has our value, the int? will provide a clean fail safe if it can't cast. It in essence will be null if it fails. Which is easy to work with.
Once you have said Id you can call your database and actually perform desired query.
Hopefully this helps.

asp:Hyperlink returning null in Formview

I have a asp:Hyperlink set up in my applications' formview and a label
<br />
<b>Posting Site:</b>
<asp:Label ID="AppleLabel" runat="server" Text='<%# Bind("Apple") %>' />
<br />
<asp:HyperLink ID="hplPostIt" Text="Text" runat="server"/>
and in my Page_Load event I attempt to find the label and the hyperlink:
Label Apple = FormView1.FindControl("Apple") as Label;
HyperLink hplPostIt = FormView1.FindControl("hplPostIt") as HyperLink;
Then I try to use an if statement to change the NavigateURL property of the hyperlink based on the text of the label and Visual Studio complains that the object reference is not set. Here is my if else condition:
if (!Page.IsPostBack)
{
lblRow.Text = Request.QueryString["num"];
hplPostIt.Text = "Eat Now";
if (Fruit.Text == "Fruit")
{
hplPostIt.NavigateUrl =
"https://www.mysite.com/Fruit/Apples.aspx?Season=" +
SeasonLabel.Text + "&Color_Date=" + TypeLabel.Text +
"&num=" + SeasonLabel.Text;
}
else
{
hplPostIt.NavigateUrl =
"Fruit/Apples.aspx?Season=" + SeasonLabel.Text +
"&Color_Date=" + TypeLabel.Text + "&num=" + SeasonLabel.Text;
}
}
Edited
I left out the Postback check
I have also tried using this in a protected void FormView1_DataBound(object sender, EventArgs e) with no luck
I made lot of assumptions and added some code to make a working example for you. In case you think I did not get you, please add some more information by commenting on my answer of editing your question!
Assumptions
Class Fruit - representing your dataContainer - simplified it, to store a name
on Page_Load I bound some demo values
added a paging functionality to provide a working example
Solution
I used a customMethod(..) to bind on property NavigateUrl
added string.Format(..) to concat your strings
Still unclear
Where do SeasonLabel and TypeLabel come from?
Markup
<form id="form1" runat="server">
<div>
<asp:FormView ID="fvFruits" runat="server" AllowPaging="True"
OnPageIndexChanging="fvFruits_PageIndexChanging">
<ItemTemplate>
<asp:Label ID="lblFruit" runat="server" Text='<%# Bind("Name") %>' />
<asp:HyperLink ID="hplPostIt" Text="yourText"
NavigateUrl='<%# customMethod(Eval("Name")) %>' runat="server"/>
</ItemTemplate>
</asp:FormView>
</div>
</form>
CodeBehind
protected void Page_Load(object sender, EventArgs e)
{
// demo purposes to add some data
if (!Page.IsPostBack)
bindDemoData();
}
private void bindDemoData()
{
List<Fruit> fruits = new List<Fruit>();
fruits.Add(new Fruit() { Name = "Apple" });
fruits.Add(new Fruit() { Name = "Banana" });
fruits.Add(new Fruit() { Name = "Orange" });
fvFruits.DataSource = fruits;
fvFruits.DataBind();
}
/// <summary>
/// Custom method to check for a given parameter value, which will be given
/// by the dataBinding within markup code.
/// You might even pass more parameter values
/// </summary>
/// <param name="fruit">the name of the fruit</param>
/// <returns>custom link for each given fruitName</returns>
public string customMethod(object fruit)
{
if (fruit != null)
{
string fruitName = fruit.ToString();
// insert custom binding here!
string url = "https://www.mysite.com/Fruit/";
if (fruitName == "Apple")
url += "Apples.aspx";
else if (fruitName == "Banana")
url += "Banana.aspx";
else if (fruitName == "Orange")
url += "Orange.aspx";
/*else
url += "defaultFruit.aspx";; // up to you*/
// can't see where SeasonLabel and TypeLabel are defined??? please add a comment if I did get you wrong
url += string.Format("?Season={0}&Color_Date={1}&num={2}", SeasonLabel.Text, TypeLabel.Text, SeasonLabel.Text);
//uncomment this line and comment out the line above to get a working example
//url += string.Format("?Season={0}&Color_Date={1}&num={2}", "a", "b", "c");
return url;
}
return "https://www.mysite.com/error.aspx"; // probably - but up to you
}
protected void fvFruits_PageIndexChanging(object sender, FormViewPageEventArgs e)
{
fvFruits.PageIndex = e.NewPageIndex;
bindDemoData();
}
// demo data container
public class Fruit
{
public string Name { get; set; }
}
Result Pic
First of all, use string.Format to format a url string
hplPostIt.NavigateUrl = string.Format("https://www.mysite.com/Fruit/Apples.aspx?Season={0}&Color_Date={1}&num={2}", SeasonLabel.Text, TypeLabel.Text, SeasonLabel.Text);
Second
You don't need FindControl to access to hplPostIt, if it located directly on Page. See "youpagename.aspx.design.cs" to find control declaration
Third
Probably null reference exception thrown by one of text control (SeasonLabel, TypeLabel)
Have you tried running it in the formview databound event rather than page load?
Something like:
<asp:FormView ID="FormView1" runat="server" OnDataBound="FormView1_DataBound" ...>
and in the code behind
protected void FormView1_DataBound(object sender, EventArgs e)
{
Label Apple = FormView1.FindControl("Apple") as Label;
HyperLink hplPostIt = FormView1.FindControl("hplPostIt") as HyperLink;
// etc.
}
As a workaround
<asp:HyperLink ID="hplPostIt" runat="server" NavigateUrl='<%# getLink(Eval("Apple")) >' />
Then
protected string getLink(object obj)
{
string fruit = obj.ToString();
// if else with fruit string.
}

data pager in listview Issue

I have a listview where in I placed datapager as follows.
I am using SQl datasource and binding the records to ListView.
asp:ListView runat="server" ID="ListView1" DataKeyNames="ProductId,GameName" DataSourceID="GameTable" OnItemCommand="On_Select_Item"
and datapager in the LayoutTemplate
And in the item template I am placing a button, when clicked it calls a method where i am trying to fetch DatakeyName values. It is working fine in first page when pager is given, However when moved to other page in the pager, it is throwing me an exception.
Here is the button click code,
protected void On_Select_Item(object sender, ListViewCommandEventArgs e)
{
if (String.Equals(e.CommandName, "AddtoCart"))
{
//checks if the user is logged in
if (User.Identity.IsAuthenticated)
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
DropDownList dl = e.Item.FindControl("DropDownList") as DropDownList;
String val="";
if (dl != null)
{
val = dl.SelectedValue; //Get the selected value from DropDownList
}
String price = Convert.ToString(e.CommandArgument).Trim(); //Get the price for the selected game.
-------------Exception is thrown at below line ---------
string ProductId =
ListView1.DataKeys[dataItem.DataItemIndex]["ProductId"].ToString(); //Product Id for the selected game.
string GameName = ListView1.DataKeys[dataItem.DataItemIndex]["GameName"].ToString(); //gamename
...............................
.............................
}
Define a grid first (you can change the control name to listView but the implementation is the same )
<asp:GridView runat="server" ID="grdResult"
CellPadding="2"
OnPageIndexChanging="grdResult_PageIndexChanging"
GridLines="None"
Width="100%"
AllowSorting="True"
AllowPaging="True"
Then in the bottom define a data source
<asp:SqlDataSource ID="sqlGridData" runat="server"></asp:SqlDataSource>
now in the code behind load your sqlGridData control with data (it accepts many parameters like datatable, odbcrecordset you can use .provider property mentioned here http://tinyurl.com/bllyjsz ) if you have static data them you even mention at the design time (as done here http://tinyurl.com/c8b6mbh)
private void BindDataGrid()
{
sqlGridData.Provider = dataReader;
grdResult.DataSourceID = "xmlGridData";
//grdResult.PageIndex = 0;
}
Try this and do let me know if you have any query.

how can find every item INFO inside a repeater (in ItemCommand event) - repeater datasource is a List<> collection

i have a list collection like below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace FileExplorer.Classes
{
public class NewAddedFiles
{
public string FileName { get; set; }
public string FilePath { get; set; }
public DateTime FileCreationDate { get; set; }
}
}
private void GetFilesFromDirectory(string PhysicalPath)
{
DirectoryInfo Dir = new DirectoryInfo(PhysicalPath);
FileInfo[] FileList = Dir.GetFiles("*.*", SearchOption.AllDirectories);
List<NewAddedFiles> list = new List<NewAddedFiles>();
foreach (FileInfo FI in FileList)
{
NewAddedFiles NewAddedFile = new NewAddedFiles();
string AbsoluteFilePath = FI.FullName;
string RelativeFilePath = string RelativeFilePath = "~/" + (AbsoluteFilePath.Replace(Request.ServerVariables["APPL_PHYSICAL_PATH"], String.Empty)).Replace("\\", "/");
NewAddedFile.FileName = FI.Name;
NewAddedFile.FilePath = RelativeFilePath;
NewAddedFile.FileCreationDate = FI.CreationTime;
list.Add(NewAddedFile);
}
Repeater1.DataSource = list;
Repeater1.DataBind();
}
my repeater in aspx is like below :
<asp:Repeater ID="Repeater1" runat="server"
onitemcommand="Repeater1_ItemCommand">
<ItemTemplate>
<asp:Image ID="imgArrowIconInsideRepeater" runat="server" ImageUrl="~/Images/Login/ArrowIcon.png" />
<asp:LinkButton ID="lbFile" runat="server" CommandName="lbFile_Click" CssClass="lbFileInRepeater"><%# Eval("FileName")%></asp:LinkButton>
<br />
<asp:Label ID="lblFileCreationDate" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "FileCreationDate", "{0:yyyy/MM/dd - tt h:m:s}") %>'
CssClass="lblFileCreationDateInRepeater"></asp:Label>
<div class="EmptyDiv">
</div>
</ItemTemplate>
</asp:Repeater>
and Item_Command Of repeater in code behind :
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
NewAddedFiles currentItem = (NewAddedFiles)e.Item.DataItem;
switch (e.CommandName)
{
case "lbFile_Click":
{
if (HttpContext.Current.Session["User_ID"] != null)
{
Response.Redirect("~/HandlerForRepeater.ashx?path=" + currentItem.FilePath);
}
else
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "alert", "alert('a');", true);
}
break;
}
default:
{
break;
}
}
}
}
my problem is currentItem is always null , when i click on every link button inside repeater!
i want to get FilePath of every link button inside repeater!
how can i do that ?
thanks in advance
From memory (and reinforced from Google searches), ItemCommand is one of the events that loads data from the ViewState. Once this happens, your original DataItem references do not exist anymore.
If you want to retrieve values from that item, as clunky as it sounds, you'll need to add a HiddenField to your Repeater ItemTemplate, like so:
<asp:HiddenField ID="filePath" runat="server" Value='<%# DataBinder.Eval(Container.DataItem, "FilePath")' />
and then replace this line:
Response.Redirect("~/HandlerForRepeater.ashx?path=" + currentItem.FilePath);
with these two lines:
HiddenField filePath = (HiddenField) e.Item.FindControl("filePath");
Response.Redirect("~/HandlerForRepeater.ashx?path=" + filePath.Value);
e.Item.DataItem is only available during the databinding event. You will need to use another method to extract the information you need. Put your primary key into a hidden field, retrieve that value, then
try something like
RepeaterItem ri = e.Item;
HiddenField pk = (HiddenField)ri.FindControl("pk");
int FileID = Convert.ToInt32(pk.Value);
// Create a NewAddedFiles object using the File's FileID (or whatever you have) and get the Filepath from that
I'm sure someone else will have a better answer than mine, but I can offer a workaround while you wait for that. You could add a hidden field that contains the FileName, and then use e.Item.FindControl("HiddenFieldFileName") to get at the value.
In most cases there is no need for a hidden field, simply put the data value you need in the CommandArgument property of the button:
<asp:LinkButton ID="lbFile" runat="server" CommandName="lbFile_Click" CommandArgument='<%# Eval("FilePath")%>' CssClass="lbFileInRepeater"><%# Eval("FileName")%></asp:LinkButton>
Then in the ItemCommand() event retrieve the value:
string filePath = e.CommandArgument.ToString()
You may need to HTML encode the value assigned to CommandArgument so it won't break the HTML.
Suggest you don't set the CommandName value as if it is the name of an event handler method "lbFile_Click". Instead use a name to indicate the intended outcome or action, in this case "Navigate".

asp:CheckBoxField in GridView - VS 2008

I have a gridview control bound to an object data source. in addition to the columns that i want to display i want to display this
<Columns>
<asp:CheckBoxField DataField="Locked" Visible="true" AccessibleHeaderText="On Hold" ReadOnly="false"/>
</Columns>
Couple of questions here:
1. If I do the above said, my page loads and certain rows have their records marked as checked and certain rows do not, as per data. However, the user is unable to click on any records to undo their check marks. It appears that this is in a disabled state.
It seems there is no onclick event with this checkboxfield. I want to update my records instantly when the user checks or unchecks each record. yes bad design here but my hands are tied
If i were to go with <asp:checkbox> within an <itemtemplate> how do i bind that to my locked column within the object datasource or do i have to do that by overiding onne of the methods of the gridview control?
To answer #2, I would go with a <asp:CheckBox> control in the <ItemTemplate> and then set the Checked property in the GridView_RowDataBound event:
protected void grdSomething_RowDataBound ( Object sender, GridViewRowEventArgs e )
{
if ( e.Row.RowType == DataControlRowType.DataRow )
{
BusinessObject data = ( BusinessObject ) e.Row.DataItem;
CheckBox chkLocked = ( CheckBox ) e.Row.FindControl( "chkLocked" );
chkLocked.Checked = data.Locked;
}
}
As for question #1, one solution that I've used in the past with good results is to have the client-side onClick event of the <asp:CheckBox> call an ASP.NET Ajax asynchronous page method (essentially a private web service) that updates the appropriate business object. This wouldn't be the simplest approach for you, but the user's experience is pretty slick (i.e. no full-page postback):
You would need a static method in your code-behind file to update the appropriate business object. Something like (this is pretty rough):
[WebMethod]
public static void ToggleLockedStatus ( string key )
{
if ( BusinessObjectDictionary.ContainsKey( key ) )
{
BusinessObjectDictionary[ key ].Locked = !BusinessObjectDictionary[ key ].Locked;
}
else
{
throw new Exception( "The business object specified was not found." );
}
}
For details on how to do this with ASP.NET Ajax, check out MSDN here.
For the click Event I could not figure out the OnClickChange either, so I rolled my own.
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Web;
using System.Web.UI.WebControls;
namespace Web.Library.Controls.Commands
{
public class CommandCheckBox : System.Web.UI.WebControls.CheckBox
{
private static readonly object EventCommand = new object();
public event CommandEventHandler Command
{
add
{
Events.AddHandler(EventCommand, value);
}
remove
{
Events.RemoveHandler(EventCommand, value);
}
}
public string CommandName
{
get
{
if (this.ViewState["CommandName"] == null)
return string.Empty;
return (string)this.ViewState["CommandName"];
}
set { this.ViewState["CommandName"] = value; }
}
public string CommandArgument
{
get
{
if (this.ViewState["CommandArgument"] == null)
return string.Empty;
return (string)this.ViewState["CommandArgument"];
}
set { this.ViewState["CommandArgument"] = value; }
}
protected virtual void OnCommand(CommandEventArgs args)
{
CommandEventHandler commandEventHand = Events[EventCommand] as CommandEventHandler;
if (commandEventHand != null)
{
commandEventHand(this, args);
}
base.RaiseBubbleEvent(this, args);
}
protected override void OnCheckedChanged(EventArgs e)
{
base.OnCheckedChanged(e);
CommandEventArgs args = new CommandEventArgs(this.CommandName, this.CommandArgument);
this.OnCommand(args);
}
public CommandCheckBox()
{
}
}
}
As for the databind and updating I just handled it myself on GridRowCommand.
Your control is locked because the GridView will only let you edit a row if the row is in Edit mode. I think what you're really looking for is a checkbox defined in a TemplateField. Then you can either set the initial "checked" value in the code behind or by doing something like:
<asp:CheckBox ID="MyCheckBox" runat="server" Checked='<%#Eval("Locked")' ... />
As for the trigger, you can point the OnCheckedChange property to the function of your choosing, but I'm not sure how you'd tell it which row was checked.
A better alternative could be to use the Button or ImageButton control to do the same thing. That way you can populate the CommandArgument with the row ID or whatever you need and you'll have access to it when you handle the RowCommand of the GridView.

Categories

Resources