Passing value from Page to UserControl - c#

Good day. I have a trouble with pass data between webform and UserControl.
I have the webform webform1.aspx. And i have a component GridView1. I also have UserControl - grdControl.ascx.
In webform1.aspx i mention UserControl:
<uc1:grdcontrol runat="server" id="grdControl" />
Also webform1.aspx.cs contains an event
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
grdControl.SelectedValue = GridView1.SelectedValue.ToString();
}
In turn UserControl grdControl.ascx.cs contains the following code:
private string _selectedValue;
public string SelectedValue
{
get { return _selectedValue; }
set { _selectedValue = value; }
}
In grdControl.ascx i use label and i try to get value SelectedValue and use it as text for Label1.
<asp:Label ID="Label2" runat="server" Text='<%# SelectedValue%>' ></asp:Label>
But is don't work correctly. In a web page i see nothing.

Setting the value of the label in the PreRender event of the code behind should fix it.
I'm thinking that GridView1_SelectedIndexChanged will get called after the Page_Load event of the inner grid control that's why the value is blank because you are trying to set it in the page itself and that happens in the Pre_init function of the inner control. I don't think SelectedValue would be set at that point.

Related

Cannot get new value of control in popup modal

Do web controls ever appear like you are changing their values but actually retain the previous value?
I created a pop-up modal for users to edit an item. When the user clicks edit on an item on the main page, the following sequence happens:
The item's ID is passed to the Page_Load event of the modal page, and is used to populate the page control's with the item's data.
The user changes a value in a control. Ex: Changes text in a TextBox contol.
The user clicks save, triggering the Click event which creates a DataTransferObject with the values in the textboxes, which will be stored.
However, on step 3, the control's new value (TextBox.Text) still holds the value that it orginially had, not the value the user put in.
Add.aspx:
<%# MasterType VirtualPath="../MasterPages/Popup.Master" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:TextBox ID="TextBoxDescription" runat="server"></asp:TextBox>
<telerik:RadButton ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click"/>
</asp:Content>
Add.aspx.cs
//Cannot access the new values here
protected void btnSave_Click(object sender, EventArgs e)
{
//This will print the new text on Create, but the old text on Edit
System.Diagnostics.Debug.WriteLine(TextBoxDescription.Text);
}
//works properly
protected void Page_Load(object sender, EventArgs e)
{
objIDParam = Convert.ToInt64(Request.QueryString["ObjectID"]);
editMode = (objIDParam != 0) ? true : false;
if(editMode)
PopulateFields(objID);
}
//works properly
private void PopulateFields(long objID)
{
MyObject obj = GetObjectByID(objID);
TextBoxDescription.Text = obj.Description;
}
It is worth noting that this popup page is used for both creating items AND editing items. Create works fine (i.e. The item isn't saved with all blanks, but rather the user input). Editing an item will properly pull all that data back in, and let the user edit the fields, however I can't access the changed values in my code.
You need to check for IsPostBack in the Page_Load method.
The Page_Load gets called before the btnSave_Click method, so the TextBoxDescription.Text is getting reset to obj.Description before the btn_Save method runs.
Try returning out of Page_Load if you're posting back:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
objIDParam = Convert.ToInt64(Request.QueryString["ObjectID"]);
editMode = (objIDParam != 0) ? true : false;
if(editMode)
PopulateFields(objID);
}
Have a look at ASP.NET Page Life Cycle Overview for more info.

set SkinID Programmatically

I have GridView to display data as Label
<ItemTemplate>
<asp:Label ID="lblIsActive" runat="server" Text='<%# GetIcon((String)Eval("IS_ACTIVE"))%>' SkinID='<%# GetSkinId((String)Eval("IS_ACTIVE"))%>' />
</ItemTemplate>
c#
protected string GetSkinId(string name)
{
if (name == "Y")
{
return "sknActive";
}
else
return "sknInactive";
}
but I get error I can't set SkinID Programmatically, any idea how I can allow SkinID in code behind?
Updated
I decide to not make SkinID, so I'm doing this
<ItemTemplate>
<asp:Label ID="lblIsActive" runat="server" Text='<%# GetIcon((String)Eval("IS_ACTIVE"))%>'
ForeColor='<%# GetColor((String)Eval("IS_ACTIVE"))%>' />
</ItemTemplate>
And my function on c# to get color
protected string GetColor(string name)
{
if (name == "Y")
{
return "#99099";
}
else
return "#03211";
}
I get error that
string can not convert to System.Drawing
The error message is self explanatory. Based on the data source you have the control in your gridview is dynamically getting created and after this it is trying to set the SkinId property and thus the error.
You can achieve this when the row is getting created in your gridview. Yes you can use the RowCreated event of gridvew like this:-
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label lblIsActive = e.Row.FindControl("lblIsActive") as Label;
if(lblIsActive.Text == "Y")
lblIsActive.SkinID = "sknActive";
else
lblIsActive.SkinID = "sknInactive";
}
}
Please note that this won't work in RowDataBound event since this event is fired after the row is created and when a data row is bound to data.
Update:
First of all your assumption is wrong that we are looping actually we are not. We are simply handling the event which is raised by the gridview control. Anyways since now you have changed your mind and switched to ForeColor approach the problem with your code is that the ForeColor property expects a System.Drawin.Color enum but your passing a string thus the error. For correctint you will have to return Color instead of string like this:-
protected Color GetColor(string name)
{
if (name == "Y")
return Color.Red;
else
return Color.Green;
}
Here I am returning sample colors but you need to replace them with actual intended colors. If you just have the hex string and not sure about the Color enum value then you can use the method mentioned in this answer to do so.
The error message tells you what you need to do: move the initializing of the SkinID property to the Page_PreInit stage of the page lifecycle.
Basically, this entails adding the following event handler to your code behind:
protected void Page_PreInit(object sender, EventArgs e)
{
lblIsActive.SkinId = GetSkinID(IS_ACTIVE); // no need for eval here
}

Dynamically added items don't raise events.(ASP.NET ListBox)

My code is:
private void Add_Items()
{
for (int x = 1; x < 53; x++)
{
ListBox1.Items.Add("Item" + x);
ListBox1.DataValueField = "Value" + x;
}
}
None of these items raises SelectedIndexChanged event when clicked.
Please assist.
Make sure autopostback is enabled, like in this examle:
<asp:ListBox ID="listBoxLocation" runat="server" AutoPostBack="True"
OnSelectedIndexChanged="listBoxLocation_SelectedIndexChanged" EnableViewState="True">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
</asp:ListBox>
Or to dynamically populate:
Protected void Button1_Click (object sender, System.EventArgs e)
{
ListBox1.Items.Add(new ListItem("Carbon", "C"));
ListBox1.Items.Add(new ListItem("Oxygen", "O"));
}
From: http://msdn.microsoft.com/en-us/library/14atsyf5%28v=vs.85%29.aspx
First.
The ListBox1.DataValueField should not be set to every item. This property sets the field on the data object (each row) to capture the value from. Here is the MSDN link for this property http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.datavaluefield(v=vs.110).aspx.
Next, I am assuming you have all the front end code wired up something like.
<asp:ListBox ID="ListBox1" OnSelectedIndexChanged="ListBox1_SelectedIndexChanged" runat="server"></asp:ListBox>
This has the selected changed event wired up. However for this control to actually Post the data back you need to provide one more attribute. Add
AutoPostBack="true"
To your control as.
<asp:ListBox ID="ListBox1" OnSelectedIndexChanged="ListBox1_SelectedIndexChanged" AutoPostBack="true" runat="server"></asp:ListBox>
This starts the magic. MSDN for AutoPostBack: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.autopostback(v=vs.110).aspx
Your code is very vague, and im going to make the assumption that your ListBox has not been linked up to a SelectedIndexChanged event in the correct way.
If you are dynamically creating the ListBox link it up as below:
public void initialize()
{
ListBox lb = new ListBox();
lb.SelectedIndexChanged += lb_SelectedIndexChanged;
}
private void lb_SelectedIndexChanged(object sender, EventArgs e)
{
//Do Selected Index Changed Code Here
}
If you have a view/form with the control on, simply make sure that the ListBox's event has been set or naturally it will not trigger.
*EDIT 1
As noted in other answers your control is required to have PostBack set. You should also be checking the PostBack state of your page to ensure you are not redrawing your controls continuously, as this will keep resetting your Dynamically added controls.

Retrieving MasterPage textbox Control on a postback to another page

I have spend two days trying to figure out the solution to this problem, even tried ExpertExchange and still I can't get a solution. I am a very novice programmer to ASP.Net (using C#) and I DON'T want to use a string/url post
I have a MasterPage of which has a textbox called tbSearchString. It is a simple box that a user can enter something and then it does a Postback to another page SearchResults.aspx So I also have other pages, like Default.aspx that uses the MasterPage.
I have tried nearly everything and have read nearly every post I could find on the net and no mater what the Variables are always Null.
I have use this code on the searchResults loadpage event and Every one of these variables are null, even though I enter a value in the page text box and click the button to postback to the SearchResults page, the only time it works is if I am on the searchResults page and submit.
SearchResults back end page
protected void Page_Load(object sender, EventArgs e)
{
TextBox SearchString;
TextBox SearchString2;
TextBox SearchString3;
TextBox SearchString5;
if (Page.PreviousPage != null) //This is true on every test
{
SearchString = (TextBox)Page.PreviousPage.Master.FindControl("tbSearchString");
SearchString2 = (TextBox)PreviousPage.Master.FindControl("tbSearchString");
SearchString3 = (TextBox)Master.FindControl("tbSearchString");
TextBox LoginControlx = (TextBox)PreviousPage.FindControl("Form1");
if (LoginControlx != null)
{
TextBox SearchString4 = (TextBox)LoginControlx.FindControl("tbSearchString");
}
}
MainWebsite.Master page Code
<asp:TextBox ID="tbSearchString" runat="server"></asp:TextBox>
<asp:Button ID="btnSearch1" runat="server" Text="Search" PostBackUrl="~/SearchResultRentalEquiptment.aspx" />
I don't have anything in the CS backend page
So on the Default.aspx page
nothing special Just the Masterpage and some text content, I enter some text in the textbox goes to the SearchResults page and I can not get the darn value from the Textbox control from the Default or any other page.
What say you wise ones?
how do you redirect your form to search result form? if you are using Response.redirect, the value under Page.PreviousPage.Master.FindControl will be null . Try to use Server.Transfer to see if it works.
Here's one way:
Assuming this is your Master Page code:
<asp:TextBox ID="searchbox" runat="server" /><br />
<asp:Button ID="sendSearch" runat="server" PostBackUrl="~/Results.aspx" Text="Search" />
At the end of the day, it's all about HTTP POST, so in the target page Results.aspx PageLoad:
protected void Page_Load(object sender, EventArgs e)
{
string _foo = Request.Form[this.Master.FindControl("searchbox").UniqueID];
}
Hth....
Check out Session. I use it all the time when I need to get data from one page to another. I'm not currently able to write out a full example for you, but off the top of my head the following should work:
//page1.aspx:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string greetingString = "Hello";
Session["MyValue"] = greetingString;
Response.Redirect("page2.aspx");
}
//page2.aspx:
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(Session["MyValue"].ToString()); //prints "Hello"
}

On Postback, the DataTable data source for a Repeater is empty?

Background
I have a User Control (an .ascx file) which is being dynamically inserting into an asp:PlaceHolder control on a page. That User Control contains an asp:Repeater, which I'm binding to a DataTable.
Theoretically, on the User Control's first load the DataTable is initialized and 3 empty rows are added. A button on the User Control adds additional empty rows to the Repeater, one at a time.
Problem
The issue is that after any PostBack event on the page (namely the button in this example being clicked), the DataTable for the Repeater is empty.
User Control (.ascx)
(simplified)
<asp:TextBox ID="controlOutsideRepeater" runat="server" />
<asp:Repeater ID="myRepeater" runat="server">
<ItemTemplate>
<p><asp:Textbox ID="firstControlInRepeater" runat="server" text='<%# DataBinder.Eval(Container.DataItem, "A") %>' /></p>
<p><asp:Textbox ID="secondControlInRepeater" runat="server" text='<%# DataBinder.Eval(Container.DataItem, "B") %>' /></p>
</ItemTemplate>
</asp:Repeater>
<asp:LinkButton ID="addItemButton" runat="server" Text="Add Item" onclick="addNewItem" />
Code Behind (.ascx.cs)
(also simplified)
public DataTable items {
get {
object i = ViewState["items"];
if (i == null) {
DataTable t = new DataTable();
t.Columns.Add("A");
t.Columns.Add("B");
// add 3 blank items/rows:
t.Rows.Add(t.NewRow());
t.Rows.Add(t.NewRow());
t.Rows.Add(t.NewRow());
ViewState["items"] = t;
return t;
} else {
return (DataTable)i;
}
set { ViewState["items"] = value; }
}
protected void Page_Init(object sender, EventArgs e) {
myRepeater.DataSource = this.items;
myRepeater.DataBind();
}
public void addNewItem(object sender, EventArgs e) {
DataRow r = this.items.NewRow();
this.items.Rows.Add(r);
myRepeater.DataBind();
}
Behavior
The first time the UserControl is loaded, the Repeater contains 3 empty items: good! However, after entering some text in the textboxes both inside and outside the repeater and clicking the "Add Item" LinkButton, the page does a refresh/postback and shows 4 empty items, however the textbox -outside- the Repeater retains it's text. Clicking the "Add Item" LinkButton again also performs a postback and still shows 4 empty items, yet the TextBox outside the Repeater again retains it's text.
My Crazy Guess
I've tried wrapping the Repeater databinding in a (!Page.IsPostBack), but this prevented the Repeater from -ever- being bound, as the UserControl is only programmatically added to the page after a PostBack (a button on the Page adds the UserControl on a click, and then the Page checks each PostBack to see if there should be a user control present and re-adds it to the Page if needed). So I'm guessing there's a problem with the Page re-creating the User Control on every PostBack, but can't explain why the TextBox outside the Repeater would retain it's value, and why the ViewState doesn't seem to remember my item (on each postback ViewState["items"] is null and gets re-built within the getter).
HELP!
The problem is you are data binding every single request when really you only want to data bind on the first request. Since you don't data bind on the first page load, you will have to check if you are data bound in a way other than !Page.IsPostBack. You could add a property to your user control to handle this and then check against that every page load / page init.
Update: With more details from comments
I see your AddItem() now. I've had problems using viewstate this way though I'm not entirely sure why. I've had to do it more like the following:
public void addNewItem(object sender, EventArgs e) {
DataTable theItems = this.items;
DataRow r = theItems.NewRow()
theItems.Rows.Add(r);
this.items = theItems
myRepeater.DataBind(); //I'm not sure if this belongs here because of the reasons said before
}

Categories