I want RowCommand executed before RowCreate reloading OR something like this - asp.net

I have
<asp:GridView>
<asp:TemplateField HeaderText="PsyHealth">
<ItemTemplate>
<asp:PlaceHolder runat="server" ID="PsyHealth" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="-">
<ItemTemplate>
<asp:LinkButton ID="Gen" CommandName="Gen" runat="server" Text="gen" />
</ItemTemplate>
</asp:TemplateField>
and
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var dataItem = e.Row.DataItem as ViewModels.UserTestorViewModel;
var psyHealth = e.Row.FindControl("PsyHealth") as PlaceHolder;
if (psyHealth != null)
{
psyHealth.Controls.Add(dataItem.PsyHeath);
}
}
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
//bla bla bla
}
but when I clicked the Gen LinkButton on the page. The GridView1_RowCreated was triggered first and threw the error Object reference not set to an instance of an object because the e.Row.DataItem was null.
Edit: The Code Behind
protected void Page_Load(object sender, EventArgs e)
{
List<ViewModels.UserTestorViewModel> utViewModelList = new List<ViewModels.UserTestorViewModel> { };
utViewModelList = utRepo.GetUserTestorViewModelListByHrId();
this.GridView1.DataSource = utViewModelList;
this.GridView1.DataBind();
if (!IsPostBack)
{
}
}
protected void Page_Init(object sender, EventArgs e)
{
GridView1.RowCreated += new GridViewRowEventHandler(GridView1_RowCreated);
}

Can you store the utViewModelList in Session first time you get it? If so then you can get the UserTestorViewModel instance from saved by the selected row's DataKey value.

When you click any button in the gridview , your page is postbacked and the page load event is called before it goes into the RowCommand event. In the page load event you are binding your gridview again and that's why your RowCreated Event is called.
You have to bind your gridview under if (!IsPostBack)
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<ViewModels.UserTestorViewModel> utViewModelList = new List<ViewModels.UserTestorViewModel> { };
utViewModelList = utRepo.GetUserTestorViewModelListByHrId();
this.GridView1.DataSource = utViewModelList;
this.GridView1.DataBind();
}
}
Edit: Now I got your issue after you posted code..
The problem is here in Page_Init, can you remove the event handler from here and try the following:
protected void Page_Init(object sender, EventArgs e)
{
GridView1.RowCreated += new GridViewRowEventHandler(GridView1_RowCreated);
}
add here
<asp:GridView onrowcreated="GridView1_RowCreated">

Related

Repeater with dynamic UC

I have a formular with dynamic data and UC.
my ascx file looks like:
<asp:Repeater ID="rMyData" runat="server" OnItemDataBound="OnRepeaterItemDataBound">
<ItemTemplate>
<asp:Panel ID="panelAdditional" runat="server"/>
</ItemTemplate>
</asp:Repeater>
and the cs file:
public partial class MyFormular
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
PrepareList();
DataBind();
}
}
private void PrepareList()
{
rMyData.DataSource = GetData();
rMyData.DataBind();
}
protected void OnRepeaterItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem repeaterItem = e.Item;
Panel panel = (Panel)repeaterItem.FindControl("panelAdditional");
if (panel != null)
{
var datarow= (Data)repeaterItem.DataItem;
if (datarow!= null)
{
panel.Controls.Clear();
MyUC ctrl;
ctrl = (MyUC)Page.LoadControl("~/MyUC.ascx");
ctrl.Enabled = true;
ctrl.DataRow = datarow;
panel.Controls.Add(ctrl);
}
}
}
protected void SaveNewsletterSubscription(object sender, EventArgs e)
{
...
}
}
My problem is, it doesn't show my UC.
If I put my PrepareList() and DataBind() outside of the PostBack, it works perfectly fine and shows my UC. But after I press the save Button, it reloads the page and rebind my repeater. So I lost everything in the UC.
Why does it only show my UC if I rebind it in every pageload?
I hope the I posted enough information.

ASP.NET listview double click

Can I use double-click on a asp.net listview? I want to call a function on double-click rather than single i.e ItemCommand.
Is it at all possible?
Ta!
ASPX:
<asp:ListView ID="ListView1" runat="server"
onitemdatabound="ListView1_ItemDataBound" onitemcommand="ListView1_ItemCommand">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" CommandName="DoubleClick" runat="server">LinkButton</asp:LinkButton>
</ItemTemplate>
</asp:ListView>
CS:
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
LinkButton LinkButton1 = (LinkButton)e.Item.FindControl("LinkButton1");
string _jsDouble = ClientScript.GetPostBackClientHyperlink(LinkButton1, "");
LinkButton1.Attributes["ondblclick"] = _jsDouble;
LinkButton1.Attributes["onclick"] = "return false;";
}
}
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "DoubleClick")
{
}
}
If calling function is referring to server side call simple thing would be
private void listView_MouseDoubleClick(object sender, MouseEventArgs e)
{
MessageBox.Show("Double Click Event Called");
}
For more info on same check:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doubleclick.aspx
And if calling function refers to any client side (Javascript/Jquery call) then you can use:
$('#target').dblclick(function() {
alert('Handler for .dblclick() called.');
})
for more info check here

Dropdownlist in gridview not firing selectedindex changed event

I have problem with not firing selected index changed event of dropdownlist in gridview. I gone through the SO Thread . It is not worked wholly for me. I have implementation like below.
.ASPX
<asp:DropDownList ID="DDL1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="DDL1_SelectedIndexChanged">
<asp:ListItem Text="Review" Value="Review" Selected="True">Review</asp:ListItem>
<asp:ListItem Text="Level1" Value="lvl1">Send Back to Level1</asp:ListItem>
</asp:DropDownList>
.CS
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
// Bind the GridView to something.
DataBindGrid();
}
else {
// Bind the GridView again to maintain previous entered data in the gridview
DataBindGrid();
}
}
protected void DDL1_SelectedIndexChanged(object sender, EventArgs e)
{
this.lblCity.Text = ((DropDownList)sender).SelectedValue;
}
protected void grdPoll_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(Page.IsPostBack)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl = e.Row.FindControl("DDL1") as DropDownList;
if(ddl != null)
{
ddl.SelectedIndexChanged += new EventHandler(DDL1_SelectedIndexChanged);
}
}
}
}
When i keep if(!Page.IsPostBack) block only then it works fine. But i want else block also. Whats going wrong with implentation. Can you please suggest the solutions
The problem is block after !Page.IsPostBack block, which is not event else part as you said. You are binding grid again on post back which results in loss of the event being fired. You do not have to bind it again to have the changes in the grid.
Remove this code.
{
// Bind the GridView again to maintain previous entered data in the gridview
DataBindGrid();
}
Try this:
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
// Bind the GridView to something.
DataBindGrid();
}
else {
// Bind the GridView again to maintain previous entered data in the gridview
//DataBindGrid(); //remove DataBindGrid(); from else
}
}
protected void DDL1_SelectedIndexChanged(object sender, EventArgs e)
{
this.lblCity.Text = ((DropDownList)sender).SelectedValue;
DataBindGrid();
}
replace event name "Page_Load" with "Page_PreRender"

Populate different gridview by clicking different button

In my web page header, there are several buttons. What I want is to click each button to display a desired table in a gridview.
click button1
Display table in gridview 1.
click button2 Display table in gridview 2, Gridview 1 disappeared.
The header and buttons are persisting in the page. I don't want to redirect the current page to different pages. I only want to implement the function in one web page.
ASPX
<div>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
<asp:GridView ID="GridView2" runat="server">
</asp:GridView>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<asp:Button ID="Button2" runat="server" Text="Button" onclick="Button2_Click" />
</div>
C#
protected void Button1_Click(object sender, EventArgs e)
{
GridView1.Visible = true;
GridView2.Visible = !GridView1.Visible;
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
GridView1.Visible = false;
GridView2.Visible = !GridView1.Visible;
GridView2.DataBind();
}
You may need to pass in the .DataBind() call depending on how you are binding your data to the gridviews.
On each button click just bind your GridView as needed. For example:
Button1 clicked do:
protected void Button1_OnClick(object sender, EventArgs e)
{
grdYourGrid1.DataSource = yourDataSource;
grdYourGrid1.DataBind();
grdYourGrid1.Visible = true;
grdYourGrid2.DataSource = null;
grdYourGrid2.DataBind();
grdYourGrid2.Visible = false;
}
Then do the opposite for Button2. I suggest rebinding and nulling the non visible grid so the ViewState doesn't get bloated when not required.
You can put this in the Page_Load
button1.Click+=(s,ev)=>
{
gridview1.visible = true;
gridview1.DataBind();
};
button2.Click+=(s,ev)=>
{
gridview2.DataBind();
gridview1.visible = false;
};
C#
buttin1_Onclick(object sender, EventArgs e)
{ gridview1.visible = true; gridview1.DataBind(); gridview2.visible = false;}
buttin2_Onclick(object sender, EventArgs e)
{ gridview2.visible = true; gridview2.DataBind(); gridview1.visible = false;}
or
buttin1_Onclick(object sender, EventArgs e)
{ gridview1.DataBind(); gridview2.Rows.Clear();}
buttin2_Onclick(object sender, EventArgs e)
{ gridview2.DataBind(); gridview1.Rows.Clear();}

modify datarow value for a specific gridview column

how would i change the value IBM to something arbitrary like Cisco in one of the gridview events listed?
there can be varying columns in the dynamic gridview so would be nice to address the column by name.
namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable("TestTable");
dt.Columns.AddRange(new DataColumn[] { new DataColumn("id"), new DataColumn("customername") });
DataRow dr = dt.NewRow();
dr[0] = "1";
dr[1] = "Microsoft";
dt.Rows.Add(dr);
DataRow dr2 = dt.NewRow();
dr2[0] = "2";
dr2[1] = "IBM";
dt.Rows.Add(dr2);
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected void GridView1_DataBinding(object sender, EventArgs e)
{
}
protected void GridView1_DataBound(object sender, EventArgs e)
{
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
}
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
}
}
}
This won't work when AutogenerateColumns is set to true(default). You need to add the columns programmatically or declaratively(in aspx markup). Then you can use a TemplateField with a Control like Label that you can reference in codebehind:
For example:
<asp:GridView ID="GridView1" AutoGenerateColumns="false" OnRowDataBound="GridView1_RowDataBound" runat="server">
<Columns>
<asp:TemplateField HeaderText="Customer">
<ItemTemplate>
<asp:Label ID="LblCustomer" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
RowDataBound is perfect(for almost everything):
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow) {
var row = ((DataRowView)e.Row.DataItem).Row;
var lblCustomer = (Label)e.Row.FindControl("LblCustomer");
var customerName = row.Field<String>( "customername" );
if(customerName == "Microsoft") {
customerName = "Cisco";
}
lblCustomer.Text = customerName;
}
}
Edit: Ok, never needed to do such. But actually you can change the Microsoft values to Cisco even with AutoGenerateColumns set to true.
DataBinding event is triggered before the GridView is databound. If you change the datasource before it's bound to grid, you'll be able to modify it:
protected void GridView1_DataBinding(object sender, EventArgs e)
{
var tbl = (DataTable)((GridView)sender).DataSource;
var msRows = tbl.AsEnumerable()
.Where(r => r.Field<String>("customername") == "Microsoft")
.Select(r => r);
foreach(DataRow msRow in msRows) {
msRow[ "customername" ] = "Cisco";
}
}
Note: of course you can also use a simple loop instead of LINQ

Resources