ASP.NET DataGrid within a Repeater - asp.net

I have a table that has two columns:
CommunityID
PersonID
And A "People" table that has (among other things):
FirstName
LastName
I would like to display a different DataGrid for each community, each datagrid having only the people that are part of that community. I would like to do this without using 4 seperate SqlDataSources.
A Repeater looks like a good way, with a DataGrid inside the ItemTemplate, but I can't seem to make heads or tails of getting that to work with the different values for each repetition.
If anyone has any suggestions on better ways to do this, I'd be very appreciative, as this is one of my first forays into the world for ASP.NET
Thanks,
Mike

Personally I wouldn't use a DataGrid control, since it restricts your control over your output and they've been replaced by the newer GridView & ListView controls (although DataGrid is not obsolete so feel free to use it if you want). You may want to consider using the alternatives but you aren't required to do so.
To do what you're looking for, you would have markup like the following:
<asp:Repeater runat="server" ID="myRepeater"
onitemdatabound="Repeater_ItemDataBound">
<ItemTemplate>
<asp:DataGrid runat="server" ID="myDataGrid">
</asp:DataGrid>
</ItemTemplate>
</asp:Repeater>
Then you'll wire up the markup with the following code-behind:
protected void Page_Load(object sender, EventArgs e)
{
myRepeater.DataSource = new Object[0];
myRepeater.DataBind();
}
protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
DataGrid dg = (DataGrid)e.Item.FindControl("myDataGrid");
object o = e.Item.DataItem;// Cast the DataItem as whatever
// your Repeater's DataSource is
// ...
// Do whatever you need to get the
// data source for your DataGrid here
// ...
dg.DataSource = DataGridSourceObjectHere;
dg.DataBind();
}
The key is the Repeater's ItemDataBound event, which is the method called every time a repeater row is created. This is where you can data bind your DataGrid source. You can put any logic you need to within this method using the RepeaterItemEventArgs parameter to access the data item you bound to your Repeater.

Related

Displaying empty rows by Telerik RadGrid while viewing page in browser

I added Telerik RadGrid in an ASP.Net project, i want while browsing the page to display multiple empty rows and i want to add data direct to the grid either text or drop down or checkbox columns. I don't want to connect to datasource just empty rows. If cannot be through RadGrid what i can use else.
If all you want are empty rows, create any object that you can iterate over, like a collection, and throw that object into the datasource of the grid. Below is a very basic example.
Example:
<telerik:RadGrid ID="RadGrid1" OnNeedDataSource="RadGrid1_NeedDataSource" runat="server">
</telerik:RadGrid>
protected void RadGrid1_NeedDataSource(object sender, EventArgs e)
{
DataTable table = new DataTable();
table.Columns.Add("Some Column", typeof(string));
table.Rows.Add(""); // Add some empty rows
table.Rows.Add("");
table.Rows.Add("");
RadGrid1.DataSource = table;
}

Populate gridview based on databound dropdown list selectedvalue change

I have an asp.net application for membership management. One page needs to have a gridview which is populated based on a dropdown list of statuses. I initially thought about hard-coding with a Select Case, but then remembered that the dropdown list is databound and needs to be dynamic (because the admin-level users have another page to change the statuses). I'm still new at this, and my searches are not turning up anything.
Any links or examples would be helpful. Thanks.
I would suggest to use OnSelectedIndexChanged event of dropdownlist for your purpose with AutoPostBack property set to true, something like this
<asp:DropDownList runat="server" ID="ddlStatus" OnSelectedIndexChanged="ddlStatus_SelectedIndexChanged" AutoPostBack="True"></asp:DropDownList>
And on your code behind page you can bind your grid differently for different selected values in your event handler, something like this
protected void ddlStatus_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddlStatus.SelectedItem.Value == "RequiredValue")
{
// bind grid in some way
}
else
{
// bind grid in some other way
}
}
This will work irrespective of your binding the dropdownlist options dynamically or having them hard coded.

How to avoid repetition of data in Gridview?

In a web application I am binding the data to a GridView. In the GridView some of data is repeating. I want to not display the data again and again.
For example Empid is displaying more than one time in the same column. I want to not display the empid again in that column.
You can implement the OnDataBinding event for the specific column you are using. I never use AutoGenerateColumns so having fine control of each cell is pretty simple to implement.
Eg:
// Create global in your .cs file
string _currentEmpID = string.Empty;
Define your column like:
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Literal ID="ltEmpID" runat="server"
OnDataBinding="ltEmpID_DataBinding" />
</ItemTemplate>
</asp:TemplateField>
<!-- Your other columns... -->
</Columns>
Then just implement your DataBinding event:
protected void ltEmpID_DataBinding(object sender, System.EventArgs e)
{
Literal lt = (Literal)(sender);
string empID = Eval("EmpID").ToString();
if (!empID.Equals(_currentEmpID))
{
lt.Text = empID;
_currentEmpID = empID;
}
else
{
lt.Text = string.Empty;
}
}
The RowDataBound forces you to search for controls and if changes are required in the future you have the possibility of breaking other things being modified within the event. Because of this, I prefer to use the control's DataBinding event whenever possible as it localizes functionality to only the control and gives you the flexability to swap out controls and functionality easily without the worry off affecting other things.
If you group your data by the columns you don't want to repeat before binding it to your datasource you can bind an event to RowDataBound and check if the current value equals the previous and then hide the cell.
Check this for an example.
Just add the property AutoGenerateColumns in the gridview and assign it the value of false.
AutoGenerateColumns="false"

ASP.NET Repeater not binding after ItemCommand

I have a repeater that is looping a user control, like this:
<asp:Repeater ID="repItems" runat="server" EnableViewState="false"
OnItemCommand="repItems_ItemCommand">
<ItemTemplate>
<dmg:confirmItem runat="server"
OnDataBinding="confirmitemItem_DataBinding"
Basket="<%# Container.DataItem %>" />
</ItemTemplate>
</asp:Repeater>
My code behind looks like this:
public void BindItems(List<ShopBasket> baskets)
{
_baskets = baskets;
repItems.DataSource = baskets;
repItems.DataBind();
}
My custom user control looks like this:
public ShopBasket Basket;
protected void Page_Load(object sender, EventArgs e)
{
imgItem.ImageUrl = ShopImagePath + Basket.ImageFilename;
...etc...
}
All works brilliantly the first time around, the basket items are bound to Basket objects and everything is great.
However, when I receive an ItemCommand from my repeater, and update the basket contents (Note: No adding or removing is done here, just updates the quantity) then I rebind to see the latest values, and BOOM! Null reference - no Basket object in the user control Page_Load. This is despite tracing through to see that the BindItems() method is called as usual, and the Baskets are there.
I presume this has something to do with the life cycle but it has me beat.
Any ideas?
Thanks
Duncan
It's a little dangerous to have a public field store an item being bound, especially when you have multiple items. A safer way to do it is to extract the Basket as the DataItem bound to the repeater, and do something with it that way in the repeater ItemCommand event. ItemDataBound would be even safer as you know the basket would be existing (since it's data bound), Page_Load is not a safe option here...
HTH.

How do I get the whole object from a ListView?

I have a asp:ListView control that I bind with a List<CustomObject>.
When Editing records in this ListView control, I can always get the Unique Id of record being edited by using:
int id = Convert.ToInt32(lstView1.DataKeys[e.NewEditIndex].Value);
Is it possible to get the whole object <CustomObject> that is being edited, using any of the ListView properties?
I just figured that out,
We can get the object being edited using following code-
protected void lstView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
ListViewDataItem objCurrentItem = (ListViewDataItem)e.Item;
**CustomObject obj = (CustomObject)objCurrentItem.DataItem;**
if (objCurrentItem.DisplayIndex == lstView1.EditIndex)
{
TextBox txtTitle = (TextBox)objCurrentItem.FindControl("txtTitle");
txtTitle.Text = obj.Title;
}
}
Here is the answer to your comment to my question:
Yes, the reason it is null in itemcommand and works fine in itemdatabound is that the location itemcommand is not correct for reading this value. You will always get the DataItem null in ItemCommand, no matter what you do. The reason lies in the control life cycle. The control gets initialized, created and then only does any other event related to the control can fire. During control creation the CreateControlHierarchy is called which then uses the DataBind event to create and databind the child controls. At that time the DataItem is live and is not null. Before that and after that it is always null, because its role lies only for that much time span.
By the way the DataItem you are looking at is the item from the related datasource that is being used to databind the listview. The datasource is used only during databinding, hence the DataItem is available only during Item Databound.
Hope this helps !
When you click on the edit for a given item in the listview the ItemCommand event gets fired. The arguments for that event tell that you can get the list item for which that event was fired. You will have to typecast that item properly to get the information you require. The itemcommand event looks like this
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
}
you have e.Item to use from the ListViewCommandEventArgs.
You item updating you don't have the object available for modifying. You only have the collection of the properties and their values in the new values and old values collections that you get from event arguments. I suppose you can edit the properties of the item over there. Its more or less similar to editing the object itself, because eventually these property values will get transferred to the object using reflection.
<asp:ListView runat="server" ID="list" OnItemCommand="listVideo_ItemCommand">
<ItemTemplate>
<asp:LinkButton ID="btDelVideo" runat="server" Text="Delete" OnClientClick="return confirm('Confirm delete ?');" CommandArgument='<%# Eval("KeyID") %>' CommandName="DELETE" />
<asp:LinkButton ID="btEditVideo" runat="server" Text="Edit" CommandArgument='<%# Eval("KeyID") %>' CommandName="EDIT" />
</ItemTemplate>
</asp:ListView>
protected void list_ItemCommand(object sender, ListViewCommandEventArgs e)
{
int videoId = (int)e.CommandArgument;
switch (e.CommandName)
{
case "DELETE":
//Implement Delete event
goto default;
case "EDIT":
//Implement Edit event
goto default;
default:
//Rebind listview
break;
}
}
}

Resources