I can't find an answer anywhere... I have a List<string[]> populated like this:
...
while (myReader.Read())
{
string[] row = new string[myInt];
for (int i = 0; i < myInt; i++)
{
row[i] = myReader[i].ToString();
}
myList.Add(row);
}
...
How do I bind this list to a gridview with TemplateField columns?
An easier way is to create an anonymous class and bind that to your GridView. Example:
var query = from c in row
select new { SomeProperty = c };
GridView.DataSource=query;
GridView.DataBind();
You can always use the RowDataBound event of the GridView
<asp:GridView ID="gridView1" runat="server"
OnRowDataBound="gridView1_DataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="myLabel" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
When binding your data:
var myStrings = new List<string[]>
{
new [] { "hello", "bye"},
new [] { "1", "2"}
};
gridView1.DataSource = myStrings;
gridView1.DataBind();
RowDataBound event:
public void gvDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType != DataControlRowType.DataRow)
{
return;
}
var item = (string[]) e.Row.DataItem;
Label myLabel = e.Row.FindControl("myLabel") as Label;
myLabel.Text = item[0];
}
Simply use databind as you normally would. To reference the column, it goes by index by default. So like this:
<asp:GridView runat="server" AutoGenerateColumns="false" ID="rpt">
<Columns>
<ItemTemplate>
<%# Eval("Key") %>
</ItemTemplate>
</Columns>
</asp:Repeater>
Dictionary<string, string> lst = new Dictionary<string, string>();
lst.Add("test", String.Empty);
lst.Add("test1", String.Empty);
this.rpt.DataSource = lst;
this.rpt.DataBind();
Related
I have this template field
<asp:TemplateField ItemStyle-Width="40px">
<HeaderTemplate>
<asp:CheckBox ID="chkboxSelectAll" runat="server" AutoPostBack="true" OnCheckedChanged="chkboxSelectAll_CheckedChanged" />
</HeaderTemplate>
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" />
<ItemTemplate>
<asp:CheckBox ID="chkEmp" runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
In the code-behind I have this code:
protected void chkboxSelectAll_CheckedChanged(object sender, EventArgs e)
{
CheckBox ChkBoxHeader = (CheckBox)grdGeral.HeaderRow.FindControl("chkboxSelectAll");
foreach (GridViewRow row in grdGeral.Rows)
{
CheckBox ChkBoxRows = (CheckBox)row.FindControl("chkEmp");
if (ChkBoxHeader.Checked == true)
{
ChkBoxRows.Checked = true;
}
else
{
ChkBoxRows.Checked = false;
}
}
}
protected void btnLista_Click(object sender, EventArgs e)
{
string strEmailTotal = "";
string strEmail = "";
foreach (GridViewRow row in grdGeral.Rows)
{
CheckBox chkBx = (CheckBox)grdGeral.FindControl("chkEmp");
if (chkBx != null)
{
if (chkBx.Checked)
{
strEmail = ((Label)grdGeral.FindControl("lblEmail")).Text;
strEmailTotal = strEmailTotal + "," + strEmail;
}
}
}
lblMail.Text = strEmailTotal ;
}
I always get a null value for the checkbox, even if I set the default value to "true" in the templatefield. Can anyone help me with this?
Thank you
In your btnLista_Click event you should use row instead grdGeral:
CheckBox chkBx = (CheckBox)row.FindControl("chkEmp");
And below this the same:
strEmail = ((Label)row.FindControl("lblEmail")).Text;
try this solution.
foreach (GridViewRow row in grdGeral.Rows)
{
CheckBox chkBx = row.FindControl("chkEmp") as CheckBox ;
}
This is my code behind code. I want to populate the DropDownList once the user clicked edit but the DropDownList I'm getting is null. Why?
protected void SupportSchedule_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "EditRow")
{
int rowIndex = ((GridViewRow)((ImageButton) e.CommandSource).NamingContainer).RowIndex;
GridViewRow row = (GridViewRow)(((ImageButton) e.CommandSource).NamingContainer);
SupportScheduleTable.EditIndex = rowIndex;
shift.Enabled = true;
resourcedate.Enabled = true;
ListItemCollection c = db.fillList();
DropDownList ddl1 = row.FindControl("ddlshiftmanager") as DropDownList;
DropDownList ddl2 = row.FindControl("ddldispatcherone") as DropDownList;
DropDownList ddl3 = row.FindControl("ddldispatchertwo") as DropDownList;
if (c != null && ddl1 != null)
{
ddl1.DataSource = c;
ddl2.DataSource = c;
ddl3.DataSource = c;
ddl1.DataBind();
ddl2.DataBind();
ddl3.DataBind();
}
getSupportSchedule();
}
else if (e.CommandName == "CancelUpdate")
{
//some codes here
} else if (e.CommandName == "UpdateRow")
{
//some codes here
}
}
//asp code
<asp:GridView ID="SupportScheduleTable" AutoGenerateColumns="False" Width="100%" runat="server" OnRowCommand="SupportSchedule_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Shift Manager">
<EditItemTemplate>
<asp:DropDownList ID="ddlshiftmanager" runat="server" Width="99%"></asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("shift_manager") %>'></asp:Label>
</ItemTemplate>
<HeaderStyle Width="32%" />
</asp:TemplateField>
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="lbEdit" CssClass="btn" ImageUrl="~/Files/edit.png" CommandArgument='<%# Eval("support_schedule_id") %>' CommandName="EditRow" runat="server"></asp:ImageButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="lbUpdate" CommandArgument='<%# Eval("support_schedule_id") %>' CommandName="UpdateRow" runat="server">Update</asp:LinkButton>
<asp:LinkButton ID="lbCancel" CommandArgument='<%# Eval("support_schedule_id") %>' CommandName="CancelUpdate" runat="server" CausesValidation="false">Cancel</asp:LinkButton>
</EditItemTemplate>
<HeaderStyle Width="2%" />
</asp:TemplateField>
//two dropdownlists before image button
</Columns>
</GridView>
I just added the ImageButton here in the recent update but this is my original code that doesn't work.
I used a SqlDataSource instead of adding the list items from the back
and this is what I used to get the selected value of the DropDownList.
else if (e.CommandName == "UpdateRow")
{
int rowIndex = ((GridViewRow)((LinkButton)e.CommandSource).NamingContainer).RowIndex;
DropDownList ddlshift = (DropDownList)SupportScheduleTable.Rows[rowIndex].FindControl("ddlshiftmanager");
DropDownList ddlone = (DropDownList)SupportScheduleTable.Rows[rowIndex].FindControl("ddldispatcherone");
DropDownList ddltwo = (DropDownList)SupportScheduleTable.Rows[rowIndex].FindControl("ddldispatchertwo");
string manager = ddlshift.SelectedValue;
string one = ddlone.SelectedValue;
string two = ddltwo.SelectedValue;
int supportID = Convert.ToInt32(e.CommandArgument);
String sh = shift.Text;
String date = resourcedate.Text;
db.updateSS(supportID, sh, manager, one, two,date);
SupportScheduleTable.EditIndex = -1;
shift.Enabled = false;
resourcedate.Enabled = false;
getSupportSchedule();
}
Your answer is a correct way to handle the issue you are seeing. But, in case you didn't figure out the actual cause...
The ImageButton you click is in your ItemTemplate. The DropDownList you want to bind is in your EditItemTemplate. lbEdit exists when you are not in edit mode but ddlshiftmanager only exists when you are.
So, the fix is to put the GridView in edit mode. Notice that this is something you actually already started to do. You need to set the EditIndex, re-bind the GridView, then get the row again. You'll then have the row in edit mode. This row should now contain ddlshiftmanager.
protected void SupportSchedule_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "EditRow")
{
int rowIndex = ((GridViewRow)((ImageButton) e.CommandSource).NamingContainer).RowIndex;
// Set the index to edit
SupportScheduleTable.EditIndex = rowIndex;
// Re-bind the GridView to put it in edit mode
SupportScheduleTable.DataSource = /* your data source */
SupportScheduleTable.DataBind();
// Get the row at the index. The row will be the
// row reflected in edit mode.
GridViewRow editRow = SupportScheduleTable.Rows[rowIndex];
// Find your DropDownLists in this edit row
DropDownList ddl1 = editRow.FindControl("ddlshiftmanager") as DropDownList;
DropDownList ddl2 = editRow.FindControl("ddldispatcherone") as DropDownList;
DropDownList ddl3 = editRow.FindControl("ddldispatchertwo") as DropDownList;
shift.Enabled = true;
resourcedate.Enabled = true;
ListItemCollection c = db.fillList();
if (c != null && ddl1 != null)
{
ddl1.DataSource = c;
ddl2.DataSource = c;
ddl3.DataSource = c;
ddl1.DataBind();
ddl2.DataBind();
ddl3.DataBind();
}
getSupportSchedule();
}
// Everything else...
}
I am trying to do when the checkbox column in my gridview is marked, I get the row index. My gridview is in a repeater and when I setup the gridview, I put a DataKeyNames:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<asp:Panel ID="pBody1" runat="server" CssClass="cpBody">
<asp:Label ID="lblBodyText1" runat="server" />
<!-- Grid view to show products based on each category -->
<asp:GridView ID="gvProduct" runat="server" AutoGenerateColumns="False" Width="998px" CellPadding="4" ForeColor="#333333" GridLines="None" ShowHeader="False" DataKeyNames="id">
<AlternatingRowStyle BackColor="White" ForeColor="#284775" />
<Columns>
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="cbCheckRow" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="name" HeaderText="Name" ItemStyle-Width="600px" />
<asp:BoundField DataField="categoryName" HeaderText="Category" />
<asp:TemplateField HeaderText="Quantity" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:TextBox ID="tbQuantity" runat="server" Width="60" Text='<%# DataBinder.Eval(Container.DataItem, "inventoryQuantity") %>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</asp:Panel>
<asp:CollapsiblePanelExtender ID="cpe1" runat="server" TargetControlID="pBody1" CollapseControlID="pHeader1"
ExpandControlID="pHeader1" Collapsed="true" ImageControlID="imgArrows1"
CollapsedImage="~/Images/downarrow.jpg"
ExpandedImage="~/Images/uparrow.jpg" TextLabelID="lblHeaderText1" CollapsedText="Show"
ExpandedText="Hide" CollapsedSize="0"
ScrollContents="false">
</asp:CollapsiblePanelExtender>
</ItemTemplate>
</asp:Repeater>
<asp:LinkButton ID="lbnConfirm" runat="server" class="btn dark" style="float: right" OnClick="lbnConfirm_Click">Confirm</asp:LinkButton>
When my lbnConfirm is onclick, I perform this to get the row index and store them into a list:
protected void lbnConfirm_Click(object sender, EventArgs e)
{
GridView gv = (GridView)Repeater1.FindControl("gvProduct") as GridView;
foreach (GridViewRow gr in gv.Rows)
{
CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
if (cb.Checked)
{
GridViewRow row = gv.SelectedRow;
string prodID = this.gv.DataKeys[row].Value.ToString();
List<DistributionStandardPackingUnitItems> distSPUList = new List<DistributionStandardPackingUnitItems>();
//Store the prodIDs into list
}
}
}
When I run the page, it told me object reference is not set to an instance at this line:
foreach (GridViewRow gr in gv.Rows)
Also the gv of this line:
string prodID = this.gv.DataKeys[row].Value.ToString();
told me that the gv does not contain a definition of missing reference. I thought I declared at the code above?
Edited Portion:
protected void lbnConfirm_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in Repeater1.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
Panel pnl = item.FindControl("pBody1") as Panel;
GridView gv = pnl.FindControl("gvProduct") as GridView;
foreach (GridViewRow gr in gv.Rows)
{
CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
if (cb.Checked)
{
string prodID = gv.DataKeys[gr.RowIndex].Value.ToString();
tempList.Add(prodID);
for (int count = 0; count < tempList.Count; count++)
{
lblTest.Text = tempList[count] + ",";
}
}
}
}
}
}
Your approach is right, however you need to consider few more things:
You have to loop through the Repeater's items and find the Panel in
each item.
You have to find the GridView inside the Panel, not in the Repeater.
You have to find the DataKey Value by RowIndex, not by row.
EDIT : To test, add a Label outside the repeater:
<asp:Label ID="lblTest" runat="server" Text=""></asp:Label>
Also change the code to display Id in the label.
After rewriting lbnConfirm_Click() method, it should look like below:
protected void lbnConfirm_Click(object sender, EventArgs e)
{
List<string> tempList = new List<string>();
foreach (RepeaterItem item in Repeater1.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
Panel pnl = item.FindControl("pBody1") as Panel;
GridView gv = pnl.FindControl("gvProduct") as GridView;
foreach (GridViewRow gr in gv.Rows)
{
CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
if (cb.Checked)
{
//GridViewRow row = gv.SelectedRow;
string prodID = gv.DataKeys[gr.RowIndex].Value.ToString();
List<DistributionStandardPackingUnitItems> distSPUList = new List<DistributionStandardPackingUnitItems>();
//Store the prodIDs into list
tempList.Add(prodID);
}
}
}
}
lblTest.Text = string.Join(",", tempList);
}
The code above worked fine in my test! Only you have to be careful not to rebind the repeater at postback in Page_Load().
Hope it helps!
get the row index in the RowDataBound event :
protected void gvProduct_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.commandName=="select")
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int index = e.Row.RowIndex;
CheckBox chk = (CheckBox)e.Row.FindControl("cbCheckRow");
int code = Convert.ToInt32(this.gvProduct.DataKeys[e.Row.RowIndex].Value);
}
}
}
Is there a clean, easy way to get a Dictionary<obj,List<obj2>> into a GridView Datasource in ASP.NET? If I just throw the Dictionary as-is into the GridView and am doing an Eval("Key") and Eval("Value"), I'll end up with the object name in the Eval("Value") column. I'm looking for a solution that provides a comma separated value in the Eval("Value") field.
GridView:
<SharePoint:SPGridView
id="GvItems"
runat="server"
AutoGenerateColumns="false"
width="100%"
AllowSorting="True" OnRowDataBound="GvItems_OnRowDataBound" >
<AlternatingRowStyle CssClass="ms-alternatingstrong" />
<Columns>
<asp:TemplateField ItemStyle-CssClass="ms-cbp" HeaderStyle-CssClass="ms-cbp" ItemStyle-VerticalAlign="Top">
<HeaderTemplate>
<asp:CheckBox ID="chkBoxSL"
runat="server"
AutoPostBack="true"
OnCheckedChanged="chkBoxSL_CheckedChanged"
style="margin-top:-1px; margin-bottom:-1px;" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkId"
runat="server"
class="padding-right: 15px;padding-top: 0px;padding-bottom: 0px" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Web Application Zone" HeaderStyle-Width="50%" HeaderStyle-CssClass="ms-vh2-nofilter-perm" SortExpression="Key">
<ItemTemplate>
<asp:Label ID="lblZone" runat="server" Text='<%# Eval("Key") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Crawl Target" HeaderStyle-Width="50%" HeaderStyle-CssClass="ms-vh2-nofilter-perm" SortExpression="Value">
<ItemTemplate>
<asp:Label ID="lblServer" runat="server" Text='<%#Eval("Value") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
Codebehind:
{
//...
var sds = new Dictionary<SPUrlZone, List<Uri>>();
foreach (var t in webApp.SiteDataServers)
{
var uriList = new List<Uri>();
foreach (var v in t.Value)
{
uriList.Add(v);
}
sds.Add(t.Key, uriList);
}
//...
GvItems.DataSource = sds;
GvItems.DataBind();
}
protected void GvItems_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.DataItem != null)
{
Label label = (Label)e.Row.FindControl("lblServer");
// extract list items
string[] uris = ((KeyValuePair<SPUrlZone, List<Uri>>)e.Row.DataItem).Value.Select(x => x.ToString()).ToArray();
label.Text = string.Join(",", uris);
}
}
Check the MSDN http://msdn.microsoft.com/en-us/library/4hx47hfe%28v=vs.110%29.aspx. Currently you are accessing List only, that's the reason why it is not evaluated as you want. Optionally you can write a method in codebehind and do it manually - personally I prefer this way.
I made small example for you:
Markup:
<asp:GridView runat="server" ID="grid1">
<Columns>
<asp:BoundField HeaderText="Key" DataField="Key"></asp:BoundField>
<asp:TemplateField HeaderText="Value">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind:
protected void Page_Load(object sender, EventArgs e)
{
Dictionary<string, List<Person>> data = new Dictionary<string, List<Person>>();
data.Add("Managers", new List<Person>() { new Person() { Age = 38, Name = "Bob" }, new Person() { Age = 45, Name = "Stephen" } });
data.Add("Developers", new List<Person>() { new Person() { Age = 25, Name = "Jake" }, new Person() { Age = 31, Name = "John" }, new Person() { Age = 27, Name = "Matthew" } });
grid1.RowDataBound += grid1_RowDataBound;
grid1.DataSource = data;
grid1.DataBind();
}
void grid1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.DataItem != null)
{
Label label = (Label)e.Row.FindControl("Label1");
// extract list items
string[] names = ((KeyValuePair<string, List<Person>>) e.Row.DataItem).Value.Select(x => x.Name).ToArray();
label.Text = string.Join(",", names);
}
}
protected class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
Or you can bind the values comma separated right from the beginning...Depends on your scenario.
I am trying to have the ddl bound when the search box returns a result. The DDL is bound as follows:
<asp:TemplateField HeaderText="Service Area" SortExpression="ServiceArea">
<EditItemTemplate>
<asp:DropDownList ID="drp_Val_ServiceArea" runat="server" DataTextField="ServiceArea"
DataValueField='<%# Eval("ServiceAreaId") %>'>
</asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lbl_Bind_ServiceArea" runat="server" Text='<%# Bind("ServiceArea") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
The page loads fine when I use the search and the grid loads.
When I press the edit button the exception is Object not set to an instance.
And errors on ddl.DataTextField = "ServiceArea".
protected void grd_User_RowEditing(object sender, GridViewEditEventArgs e)
{
grd_User.EditIndex = e.NewEditIndex;
using (var _db = new dbDataContext())
{
var result = from s in _db.tbl_ServiceAreas
where s.Deleted == false
select new
{
s.ServiceAreaId,
s.ServiceArea
};
if ((DataControlRowState.Edit) > 0)
{
DropDownList ddl = (DropDownList)grd_User.Rows[e.NewEditIndex].Cells[0].FindControl("drp_Val_ServiceArea");
ddl.DataTextField = "ServiceArea";
ddl.DataValueField = "ServiceAreaId";
ddl.DataSource = result;
ddl.DataBind();
}
}
LoadGrid();
}
Is this because the grid is already bound to the ServiceArea?
Below is the Answer I have been looking for.
protected void grd_User_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowState == DataControlRowState.Edit)
{
DropDownList ddl = (DropDownList)e.Row.FindControl("drp_Val_ServiceArea");
using (var _db = new dbDataContext())
{
var result = from s in _db.tbl_Users
where s.Deleted == false
select new
{
s.ServiceAreaId,
s.tbl_ServiceArea.ServiceArea
};
foreach (var item in result)
{
ddl.DataTextField = item.ServiceArea;
ddl.DataValueField = item.ServiceAreaId.ToString();
ddl.DataSource = result;
ddl.DataBind();
}
}
}
}