I have a repeater in my ASP.net page. I want to merge the columns which have same text. This should happen dynamically when I bind a datatable. I have searched a lot for this. But, without success. I doubt whether it is possible with a repeater. I would also like to mention that there are also image buttons and check boxes in each row.
This is my repeater source:-
<asp:Repeater ID="rpt1" runat="server" onitemcommand="rpt1_ItemCommand">
<HeaderTemplate>
<table border="1" cellpadding="10" width="50%">
<tr>
<th>Item Name</th>
<th>As On</th>
<th>Price</th>
<th></th>
<th></th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="lblRelayName" runat="server" Text='<%# Eval("ItemName") %>'></asp:Label>
</td>
<td>
<asp:Label ID="lblTimeFrom" runat="server" Text='<%# Eval("Date") %>'></asp:Label>
</td>
<td>
<asp:Label ID="lblPrice" runat="server" Text='<%# Eval("Price") %>'></asp:Label>
</td>
<td>
<asp:ImageButton ID="imgBtnStatus" runat="server"
ImageUrl="~/img/btnGet.jpg"
CommandName="Change" style="width: 36px; border-width: 0px; margin-top: -4px; vertical-align: middle;" />
</td>
<td>
<asp:CheckBox ID="chkStatus" runat="server" Checked="true" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
This is how I fill the repeater:-
protected void Page_Load(object sender, EventArgs e)
{
rpt1.DataSource = GetData();
rpt1.DataBind();
}
private DataTable GetData()
{
DataTable dt = new DataTable();
dt.Columns.Add("ItemName");
dt.Columns.Add("Date");
dt.Columns.Add("Price");
DataRow dr = dt.NewRow();
dr["ItemName"] = "Orange";
dr["Date"] = "01/01/2015";
dr["Price"] = "50";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ItemName"] = "Orange";
dr["Date"] = "02/01/2015";
dr["Price"] = "51";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ItemName"] = "Orange";
dr["Date"] = "03/01/2015";
dr["Price"] = "55";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ItemName"] = "Apple";
dr["Date"] = "01/01/2015";
dr["Price"] = "95";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ItemName"] = "Apple";
dr["Date"] = "03/01/2015";
dr["Price"] = "98";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ItemName"] = "Banana";
dr["Date"] = "01/01/2015";
dr["Price"] = "48";
dt.Rows.Add(dr);
return dt;
}
Okay, I was able to get it to look like this. I think this is what you wanted:
But I had to make significant changes to your code to make this work. Firstly, DataTable and DataRow are pretty outdated classes ... they don't support Linq, etc. So I switched to just using plain objects. Secondly, you are going to need to do the merging in your code-behind. It's still "dynamic" in the sense that you won't have to change the raw data that is coming back from the server. But you will have "process" the data before binding to the Repeater control. Here's what I ended up with:
.ASPX:
<asp:Repeater ID="rpt1" runat="server">
<HeaderTemplate>
<table border="1" cellpadding="10" width="50%">
<tr>
<th>Item Name</th>
<th>As On</th>
<th>Price</th>
<th></th>
<th></th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td style='vertical-align: top; display: <%# ((bool) Eval("IsFirstRowWithThisItemName")) ? "" : "none" %>;'
rowspan="<%# Eval("CountOfProductsWithThisItemName") %>">
<asp:Label ID="lblRelayName" runat="server" Text='<%# Eval("ItemName") %>'></asp:Label>
</td>
<td>
<asp:Label ID="lblTimeFrom" runat="server" Text='<%# Eval("ShortDate") %>'></asp:Label>
</td>
<td>
<asp:Label ID="lblPrice" runat="server" Text='<%# Eval("PriceDisplay") %>'></asp:Label>
</td>
<td>
<asp:ImageButton ID="imgBtnStatus" runat="server"
ImageUrl="~/img/btnGet.jpg"
CommandName="Change" Style="width: 36px; border-width: 0px; margin-top: -4px; vertical-align: middle;" />
</td>
<td>
<asp:CheckBox ID="chkStatus" runat="server" Checked="true" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
.ASPX.CS
public partial class About : Page
{
protected void Page_Load(object sender, EventArgs e)
{
rpt1.DataSource = this.GetMergedData(this.GetData());
rpt1.DataBind();
}
private List<Product> GetMergedData(List<Product> allProducts)
{
List<Product> mergedProducts = new List<Product>();
var groupingsByName =
allProducts
.GroupBy(product => product.ItemName);
foreach (var groupingByName in groupingsByName)
{
Product firstProduct = groupingByName.First();
firstProduct.CountOfProductsWithThisItemName = groupingByName.Count();
firstProduct.IsFirstRowWithThisItemName = true;
mergedProducts.Add(firstProduct);
mergedProducts.AddRange(groupingByName.Skip(1));
}
return mergedProducts;
}
private List<Product> GetData()
{
return new List<Product>()
{
new Product("Orange", DateTime.Parse("01/01/2015"), 50),
new Product("Orange", DateTime.Parse("02/01/2015"), 51),
new Product("Orange", DateTime.Parse("03/01/2015"), 55),
new Product("Apple", DateTime.Parse("01/01/2015"), 95),
new Product("Apple", DateTime.Parse("03/01/2015"), 98),
new Product("Banana", DateTime.Parse("01/01/2015"), 48),
};
}
}
public class Product
{
public string ItemName { get; set; }
public DateTime Date { get; set; }
public decimal Price { get; set; }
public string ShortDate { get { return this.Date.ToShortDateString(); } }
public string PriceDisplay { get { return this.Price.ToString("C"); } }
public int CountOfProductsWithThisItemName { get; set; }
public bool IsFirstRowWithThisItemName { get; set; }
public Product(string itemName, DateTime date, decimal price)
{
this.ItemName = itemName;
this.Date = date;
this.Price = price;
}
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments