Properties of WebUserControl are null in DataBind override - asp.net

I have WebUserControl with DataBind override:
public partial class WebUserControl1 : System.Web.UI.UserControl
{
public object DataSource { get; set; }
public string Text { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
}
public override void DataBind()
{
// *** there when called, properties are null, why? ***
repeater2.DataSource = DataSource;
repeater2.DataBind();
}
}
This control is in repeater with declarative bounded properties:
<asp:Repeater ID="repeater" runat="server">
<ItemTemplate>
<WebUserControl1 runat="server" DataSource='<%# DataBinder.Eval(Container.DataItem, "levels") %>' Text='<%# DataBinder.Eval(Container.DataItem, "Text") %>' />
</ItemTemplate>
</asp:Repeater>
Now when i call DataBind() on repeater:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
... data query
repeater.DataSource = items;
repeater.DataBind();
}
}
in overriden control's DataBind() method i don't have properly setted properties DataSource and Text, they are null, why?

If you have only one repeater control in WebUserControl1, it is easier to bind that child repeater control in Repeater.ItemDataBound Event of Parent repeater.
Here is the sample -
ASPX
<asp:Repeater ID="ParentRepeater" runat="server" OnItemDataBound="ParentRepeater_ItemDataBound">
<ItemTemplate>
<asp:Label runat="server" ID="StreetLabel" /><br/>
<asp:Repeater ID="ChildRepeater" runat="server">
<ItemTemplate>
<asp:Label runat="server" ID="FirstNameLabel" />
<asp:Label runat="server" ID="LastNameLabel" />
</ItemTemplate>
</asp:Repeater><hr/>
</ItemTemplate>
</asp:Repeater>
Code Behind
public class Address
{
public int Id { get; set; }
public string Street { get; set; }
public List<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ParentRepeater.DataSource = new List<Address>
{
new Address
{
Id = 1,
Street = "1st Street",
Users = new List<User>()
{
new User {Id = 1, FirstName = "John", LastName = "Doe"},
new User {Id = 1, FirstName = "Marry", LastName = "Doe"}
}
},
new Address
{
Id = 2,
Street = "2nd Street",
Users = new List<User>()
{
new User {Id = 1, FirstName = "Eric", LastName = "Newton"},
new User {Id = 1, FirstName = "John", LastName = "Newton"}
}
}
};
ParentRepeater.DataBind();
}
}
protected void ParentRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var address = e.Item.DataItem as Address;
var streetLabel = e.Item.FindControl("StreetLabel") as Label;
streetLabel.Text = address.Street;
var repeater = e.Item.FindControl("ChildRepeater") as Repeater;
repeater.ItemDataBound += ChildRepeater_ItemDataBound;
repeater.DataSource = address.Users;
repeater.DataBind();
}
}
protected void ChildRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var user = e.Item.DataItem as User;
var firstNameLabel = e.Item.FindControl("FirstNameLabel") as Label;
firstNameLabel.Text = user.FirstName;
var lastNameLabel = e.Item.FindControl("LastNameLabel") as Label;
lastNameLabel.Text = user.LastName;
}
}
Solution for Original Question
Delete public override void DataBind() event and bind repeaters2 inside PreRender event.
public partial class WebUserControl1 : System.Web.UI.UserControl
{
protected override void OnPreRender(EventArgs e)
{
repeater2.DataSource = DataSource;
repeater2.DataBind();
base.OnPreRender(e);
}
}

Related

Using ASPxComboBox with ASPxGridView, need to set initial value

I'm trying to use ASPxGridView to display a list of ASPxComboBox controls. Both the rows in the grid and the list of options in the combo boxes are populated from code. I'm having problems setting the initial value of the combo boxes.
I'm looking for it to look similar to the image below.
As you can see in the screenshot, I have been able to get both the grid view & the combo boxes to populate, but I can't figure out how to set the initial values of the combo boxes.
In the Init event of the inner combo boxes, there's no obvious property to retrieve the bound object.
I did find a couple other questions on StackOverflow, for which the answer was to add a bound property to the combo box. However, adding SelectedIndex='<%# Bind("Level") %>' to the declaration for InnerCombo gave me the error "Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control."
Here's what I have so far:
Testing.aspx:
<%# Page Title="" Language="C#" MasterPageFile="~/Light.master"
AutoEventWireup="true" CodeBehind="Testing.aspx.cs" Inherits="MyProject.Testing" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<dx:ASPxGridView ID="MyGridView" runat="server" KeyFieldName="Name">
<Columns>
<dx:GridViewDataColumn FieldName="Name" />
<dx:GridViewDataColumn FieldName="Level">
<DataItemTemplate>
<dx:ASPxComboBox
runat="server"
ID="InnerCombo"
ValueField="ID"
TextField="Desc"
ValueType="System.Int32"
OnInit="InnerCombo_Init" />
</DataItemTemplate>
</dx:GridViewDataColumn>
</Columns>
</dx:ASPxGridView>
<dx:ASPxButton runat="server" ID="btnSubmit" Text="Submit" OnClick="btnSubmit_Click" />
</asp:Content>
Testing.aspx.cs:
public partial class Testing : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.MyGridView.DataSource = GetDefaultSettings();
this.MyGridView.DataBind();
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
Debug.WriteLine("btnSubmit_Click");
for (int i = 0; i < MyGridView.VisibleRowCount; i++)
{
object[] row = (object[])MyGridView.GetRowValues(i, "Name", "Value");
// row[1] is null, but we can get the data by finding the combo box itself.
GridViewDataColumn col = (GridViewDataColumn)MyGridView.Columns["Value"];
ASPxComboBox innerCombo = (ASPxComboBox)MyGridView.FindRowCellTemplateControl(i, col, "InnerCombo");
Debug.WriteLine("{0} = {1}", row[0], innerCombo.Value);
}
}
protected void InnerCombo_Init(object sender, EventArgs e)
{
Debug.WriteLine("InnerCombo_Init");
ASPxComboBox innerCombo = sender as ASPxComboBox;
if (innerCombo != null)
{
innerCombo.DataSource = GetValues();
innerCombo.DataBind();
}
}
private static List<ValueClass> GetValues()
{
// Simple for testing; actual method will be database access.
return new List<ValueClass>()
{
new ValueClass(0, "Zero (default)"),
new ValueClass(1, "One"),
new ValueClass(2, "Two"),
new ValueClass(3, "Three"),
};
}
private static List<SettingClass> GetDefaultSettings()
{
// Simple for testing; actual method will be database access + post-processing.
return new List<SettingClass>()
{
new SettingClass("AA", 0),
new SettingClass("BB", 1),
new SettingClass("CC", 0),
};
}
public class ValueClass
{
public int ID { get; private set; }
public string Desc { get; private set; }
public ValueClass(int id, string desc)
{
this.ID = id;
this.Desc = desc;
}
}
public class SettingClass
{
public string Name { get; set; }
public int Value { get; set; }
public SettingClass(string name, int value)
{
this.Name = name;
this.Value = value;
}
}
}

How to find a string value in the radgrid by FindItemByKeyValue

Hi there i have a radgrid on which i have to find a value and if the item is found then generate message
below is my code
Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAdd.Click
If IsAlreadyExist() Then
ram.Alert("")
Else
If IsAlreadyAdded() Then
ram.Alert("")
Else
employees()
End If
End If
End Sub
and here is the IsAlreadyAdded mehtod in which iam trying to find a specific value in grid if it exists it will return false
Private Function IsAlreadyAdded() As Boolean
'If rgListnk.MasterTableView.Items.Count > 0 Then
Dim itm As GridDataItem = rgList.MasterTableView.FindItemByKeyValue("DEFAULT", "Y")
If IsNothing(itm) Then
Return False
Else
Return True
End If
End Function
Thanks...
You need to loop through each row of the Grid in order to find a value of a cell.
Make sure DataKeyNames is specified if you want to find item by FindItemByKeyValue.
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<telerik:RadGrid ID="RadGrid1" runat="server"
OnNeedDataSource="RadGrid1_NeedDataSource">
<MasterTableView DataKeyNames="Id">
</MasterTableView>
</telerik:RadGrid>
<asp:Button runat="server" ID="Button1"
OnClick="Button1_Click" Text="Submit" />
public partial class Default : System.Web.UI.Page
{
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void RadGrid1_NeedDataSource(object sender,
GridNeedDataSourceEventArgs e)
{
RadGrid1.DataSource = new List<User>
{
new User {Id = 1, FirstName = "Jon", LastName = "Doe"},
new User {Id = 2, FirstName = "Marry", LastName = "Doe"},
new User {Id = 3, FirstName = "Eric", LastName = "Newton"},
};
}
protected void Button1_Click(object sender, EventArgs e)
{
var firstItem = RadGrid1.MasterTableView.FindItemByKeyValue("Id", 1);
if (firstItem != null)
{
var firstName = firstItem["FirstName"].Text;
var lastName = firstItem["lastName"].Text;
}
foreach (GridItem item in RadGrid1.MasterTableView.Items)
{
if (item is GridDataItem)
{
var dataItem = item as GridDataItem;
var firstName = dataItem["FirstName"].Text;
var lastName = dataItem["lastName"].Text;
}
}
}
}

Gridview using Boundfield onclick event

I'm using a gridview that I want to be able to click on each row to be able to display another field from the object that I'm displaying. It feels like it's easy to solve but maybe I'm stupid because I can't find it anywhere...
The ASP-code:
<asp:GridView ID="gvMessages" runat="server" AutoGenerateColumns = "false"
CaptionAlign="NotSet" CellPadding="5">
<Columns>
<asp:BoundField HeaderText="Avsändare" DataField="Sender" />
<asp:BoundField HeaderText="Ämne" DataField="Head" />
</Columns>
</asp:GridView>
Code-Behind:
protected void Page_Load(object sender, EventArgs e)
{
gvMessages.DataSource = con.GetMails(con.GetId(Membership.GetUser().UserName));
gvMessages.DataBind();
}
Not sure that all this is necessery for the problem but here is the method in my wcf-project that is filling my composite class with object info
public List<MailInfo> GetMails(int id)
{
using (var client = new datingEntities())
{
var result = client.Mail.Where(x => x.SentTo == id).Select(x => new MailInfo
{
Message = x.Mail1,
Reciever = x.SentTo,
Read = (bool)x.IsRead,
Sender = (int)x.SentFrom,
Head = x.Subject
}).ToList();
return result;
}
}
Composite-class:
[DataContract]
public class MailInfo : Mail
{
[DataMember]
public string Message { get; set; }
[DataMember]
public int Reciever { get; set; }
[DataMember]
public bool Read { get; set; }
[DataMember]
public int Sender { get; set; }
[DataMember]
public string Head { get; set; }
}
You should databind the GridView only if(!Page.IsPostBack).
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
gvMessages.DataSource = con.GetMails(con.GetId(Membership.GetUser().UserName));
gvMessages.DataBind();
}
}
If you want to select a row on click you can use javascript:
protected void gvMessages_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow) {
e.Row.Attributes["onmouseover"] = "this.style.cursor='pointer';this.style.textDecoration='underline';";
e.Row.Attributes["onmouseout"] = "this.style.textDecoration='none';";
e.Row.ToolTip = "Click to select row";
e.Row.Attributes["onclick"] = this.Page.ClientScript.GetPostBackClientHyperlink(this.GridView1, "Select$" + e.Row.RowIndex);
}
}
Now you can handle the SelectedIndexChangedEvent whenever the user clicks somewhere in the row:
protected void gvMessages_SelectedIndexChanged(Object sender, EventArgs e)
{
// Get the currently selected row using the SelectedRow property.
GridViewRow row = CustomersGridView.SelectedRow;
}
You should use the OnSelectedIndexChanged event.
<asp:GridView ID="gvMessages" runat="server" AutoGenerateColumns = "false"
OnSelectedIndexChanged="gvMessages_SelectedIndexChanged"
CaptionAlign="NotSet" CellPadding="5">
<Columns>
<asp:BoundField HeaderText="Avsändare" DataField="Sender" />
<asp:BoundField HeaderText="Ämne" DataField="Head" />
</Columns>
</asp:GridView>
Then in the event's definition, you can retrieve the selected item and do whatever you need from there.
protected void gvMessages_SelectedIndexChanged(object sender, EventArgs e)
{
if (ContactsGridView.SelectedIndex >= 0)
ViewState["SelectedKey"] = gvMessages.SelectedValue;
else
ViewState["SelectedKey"] = null;
}
Example from the MSDN official documentation.

Databinding repeater. Property not found

Why am i getting the error that
DataBinding: _Default+Student does not contain a property called name.
This is my CodeBehind:
public class Student
{
public string name ="Name";
public string favouriteFood = "Favourite food";
public string hobby = "Hobby";
}
protected void Page_Load(object sender, EventArgs e)
{
Student nino = new Student();
nino.name = "nino";
nino.favouriteFood = "nachos";
nino.hobby = "dancing son";
Student madelene = new Student();
madelene.name = "madelene";
madelene.favouriteFood = "sushi";
madelene.hobby = "dancing casino";
Student baiba = new Student();
baiba.name = "baiba";
baiba.favouriteFood = "bitch soup";
baiba.hobby = "complaining";
ArrayList students = new ArrayList();
students.Add(madelene);
students.Add(nino);
students.Add(baiba);
testRepeater.DataSource = students;
testRepeater.DataBind();
}
This is the front:
<asp:Repeater runat="server" ID="testRepeater" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "name") %>' />"></asp:Label>
</ItemTemplate>
</asp:Repeater>
Convert the public variable name into a property like:
private string _name;
public string name
{
get
{
return _name??"Name";
}
set
{
_name = value;
}
}
It can be an auto property, if you dont need a default value ("Name") like:
public string name {get;set;}

list<type> access in webform markup

my datasource is a list of customers in a webforms project
protected void Page_Load(object sender, EventArgs e)
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer() { FirstName = "John", PhoneNumber = "999.999.9999" });
customers.Add(new Customer() { FirstName = "Jane", PhoneNumber = "999.999.9999" });
}
is there a way to iterate that in an aspx page of a web forms project. (this is easy in mvc using the model)?
Use the Repeater control for this. Here is an example:
Markup:
<asp:Repeater ID="CustomerRepeater" runat="server">
<ItemTemplate>
<span>Name:</span> <%# Eval("FirstName") %>
<span>Phone:</span> <%# Eval("PhoneNumber ") %>
</ItemTemplate>
</asp:Repeater>
Code behind:
protected void Page_Load(object sender, EventArgs e)
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer() { FirstName = "John", PhoneNumber = "999.999.9999" });
customers.Add(new Customer() { FirstName = "Jane", PhoneNumber = "999.999.9999" });
CustomerRepeater.DataSource = customers;
CustomerRepeater.DataBind();
}
Use `DataSource' of server control: (in example DropDownList)
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.ddlCustomers.DataSource = this.GetCustomers();
this.ddlCustomers.DataBind();
}
}
public List<Customer> GetCustomers()
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer() { FirstName = "John", PhoneNumber = "999.999.9999" });
customers.Add(new Customer() { FirstName = "Jane", PhoneNumber = "999.999.9999" });
return customers;
}
Default.aspx
<asp:DropDownList ID="ddlCustomers" runat="server" DataTextField="FirstName" DataValueField="FirstName"></asp:DropDownList>
Or if you needed you can use 'MVC-style' in aspx:
<% foreach(WebApplication1.Customer customer in this.GetCustomers()) { %>
<span><%= customer.FirstName %></span>
<% } %>

Resources