<asp:Repeater ID="rptProducts1" runat="server">
<ItemTemplate>
<div class="product_header">
<asp:Label ID="prodLabels" runat="server" >
<p><h4><%#Eval("Name") %></h4></p>
</asp:Label>
</div>
<div class="left-col">
<div class="img_product">
<asp:Image ID="imgProduct" runat="server" ImageUrl='<%# Eval("Picture") %>' Width="200px" Height="200px"/>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
Code Behind:
List<ProductModel> _prodObj = new List<ProductModel>();
_prodObj = response.Content.ReadAsAsync<List<ProductModel>>().Result;
_prodObj.Where(x => x.PictureId != 0).Select(v => v.Picture = "data:image/png;base64," + Convert.ToBase64String(v.PictureBinary));
var _prodname = _prodObj.Where(x=>x.Id!=0).Select(i => i.Name=""+i.Name);
try
{
rptProducts1.DataSource = _prodname;
rptProducts1.DataBind();
}
catch (Exception ex)
{
throw;
}
Issue while fetching data from the database.Want to display name and image of the product.While fetching records 'System.String' does not contain a property error is thrown.
Thanks in advance.
You are databinding your repeater to a list of String as far as I can see.
This line will fetch a list of strings:
var _prodname = _prodObj.Where(x=>x.Id!=0).Select(i => i.Name=""+i.Name);
=> _prodname will be equal to a list of names.
And then, when you databind, you have this line:
Eval("Id")
Which is essentially saying: take the current object (which is a String) and print the Id property here. But since it's a String, it has no ID property, hence your exception.
So in short: bind to the list of products you want to display (the full objects, not just the names), or change your view to not use any properties that simply aren't there.
UPDATE
If you just want to display the one product, I'd advise you to select the right product server-side before databinding your control, like this for instance:
var _prodname = _prodObj.Where(x=>x.Id!=0 && x.Id == myId).FirstOrDefault().Select(i => i.Name=""+i.Name);
... where "myId" is of course the Id you're searching for.
And then, you should use a repeater to show the data. You can just use a Label like this:
<asp:Label ID="myLabel" runat="server" />
// and server side you would do this:
myLabel.Text = _prodName;
prodObj.Where(x=>x.Id!=0)
I suspect this is failing because x is a string and not what you expect it to be.
You need to do some debugging to identify what type x is, and then trace back to find where it stops being what you expect it to be.
Also,
_prodObj.Where(x => x.PictureId != 0).Select(v => v.Picture = "data:image/png;base64," + Convert.ToBase64String(v.PictureBinary));
LINQ is evaluated lazily, unless something enumerates the result of the above expression nothing will be executed.
Related
I have less knowledge of ASP.Net. Currently, I am using ASP.Net DataGrid control and mapped all the source information in UI successfully.
myDataGrid.DataSource = MyCollectionOfObjects
myDataGrid.DataKeyField = "MyKey"
myDataGrid.DataBind()
Now, the problem is, I don't want all the objects to be mapped in the grid. Need to do some conditional filtering before mapping. Is there any feature in DataGrid that allow me to decide bind or not bind some objects?
1) One option is mapping the collection(MyCollectionOfObjects) to a new collection that contains only the required objects by applying required filtering but I am not expecting that at this moment.
For example,
foreach(var item in MyCollectionOfObjects)
{
if(item.InvalidEntry)
{
// This entry is not needed
}
else
{
// Okay with this entry
}
}
You could do something like this. Show/Hide a PlaceHolder based on the value of InvalidEntry.
<asp:TemplateColumn>
<ItemTemplate>
<asp:PlaceHolder ID="PlaceHolder2" Visible='<%# Convert.ToBoolean(Eval("InvalidEntry")) %>' runat="server">
<%# Eval("Column1") %>
</asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateColumn>
However, filtering the source data with Linq would be much easier.
myDataGrid.DataSource = MyCollectionOfObjects.Where(x => x.InvalidEntry == false);
I am using batch editing in a radgrid with save button outside the grid. In side grid there are template columns and their edit templates have multiple values. I am able to assign values to them. But when I click on save in side bath edit command method the corresponding key of newvalues gives value of [object object]
<telerik:GridTemplateColumn HeaderText="Dwg Sch" ColumnGroupName="WACompOrderEntry" UniqueName="DwgSchedule" HeaderTooltip="This is the date the factory has promised to provide approval drawings to the field (loaded automatically from Vista when available)">
<ItemTemplate>
<asp:Label runat="server" ID="lblRdDwgSch" Text='<%# Eval("Vista_Sub", "{0:M/d/yy}") %>' ToolTip="This is the date the factory has promised to provide approval drawings to the field (loaded automatically from Vista when available)"></asp:Label>
<br />
<asp:Label ID="lblDwgSch" runat="server"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<telerik:RadDatePicker ID="rdDwgSch" runat="server" Width="80px" DbSelectedDate='<%# Eval("Vista_Sub", "{0:M/d/yy}") %>' ToolTip="This is the date the factory has promised to provide approval drawings to the field (loaded automatically from Vista when available)"></telerik:RadDatePicker>
<asp:TextBox ID="txtDwgSch" runat="server" Width="80px" />
</EditItemTemplate>
</telerik:GridTemplateColumn>
Above is the template column definition
protected void gridMilestoneMatrixEntry_BatchEditCommand(object sender, GridBatchEditingEventArgs e)
{
if (e.Commands == null)
{
return;
}
Cache.Remove("MileStoneData");
var updatedCommands = e.Commands.Where(x => x.Type == GridBatchEditingCommandType.Update);
var deletedCommands = e.Commands.Where(x => x.Type == GridBatchEditingCommandType.Delete);
List<int> updatedRecords = new List<int>();
List<long> deletedRecords = new List<long>();
if (updatedCommands != null && updatedCommands.Count() > 0)
{
updatedRecords = UpdateMilestoneMatrix(updatedCommands.ToList());
}
Now inside the hashtable key values do not give values for object
updatedValues["DwgSchedule"] it gives value as [object object]
if (updatedValues["DwgSchedule"] != null)
{
tempStr = updatedValues["DwgSchedule"].ToString();
if (!string.IsNullOrEmpty(tempStr))
{
confDwgExp = DateTime.ParseExact(updatedValues["DwgSchedule"].ToString(), "M/d/yyyy", CultureInfo.InvariantCulture);
}
tempStr = string.Empty;
}
The way I decided to go about doing these things was to have the iterate through the rows of the grid by using the RadGrid.Items
This allows you to access each individual row, which in essence gives you access to the row's individual controls (i.e not just the cells, but everything on the row).
Private Sub RbtnSaveAll_Click(sender As Object, e As EventArgs) Handles RbtnSaveAll.Click
For Each item As GridDataItem In grdActivities.Items 'Iterates over the rows
'Get your controls by using item.findcontrol("controlname").
'Then send the data of the changed controls to the datasource
Next
bindGrid(True) 'Do your bind event if necessary
End Sub
If you want a c# version you can simply convert it using telerik's converter
EDIT:
<asp:Button ID="btnBulkBookOn" runat="server" Text="Book On" CommandName="Update"/>
VB-code:
Private Sub radgrdResources_UpdateCommand(sender As Object, e As GridCommandEventArgs) Handles radgrdResources.UpdateCommand
' This will be invoked when you clikc the button and fire off the Radgrid's native save.
End Sub
This really is bizarre. I'm trying to implement the AutoCompleteExtender using a database. I enter the first character, let's say 'T' into the textbox, and the drop down results panel shows all of the page's source code (client side rather than server side), one character per line as seen in the image.
AutoComplete Results Screenshot
Incidentally, Google Chrome displays this straight away, while IE has a good think about it, saying localhost is not responding because it's running a long script.
If I then select any one of those characters it then displays the correct results beginning with 'T', though replaces the character I typed with whatever I selected.
I pulled the code from a tutorial on codeproject.com and apart from changing the textbox ID and a bit of ADO so it points to my database, it's identical.
I'll include the code. What's going wrong?
Now for some reason, it's not letting me post the code, regardless of how I format, but this is what I used. AutoComplete With DataBase and AjaxControlToolkit
It is very hard to give answer without seeing the code... try this
<asp:TextBox ID="txtSearchKey" runat="server" Width="350" AutoPostBack="true" OnTextChanged="txtSearchKey_TextChanged" />
<asp:TextBoxWatermarkExtender ID="weSearchKey" runat="server" Enabled="True" TargetControlID="txtSearchKey" WatermarkText="Search by Name" WatermarkCssClass="watermark" />
<asp:AutoCompleteExtender ServiceMethod="YourWebMethod" MinimumPrefixLength="3" CompletionInterval="100" EnableCaching="false" CompletionSetCount="10" TargetControlID="txtSearchKey" ID="searchExtender" runat="server" FirstRowSelected="false" OnClientItemSelected="GetSelectedId" CompletionListCssClass="completionList" CompletionListItemCssClass="listItem" CompletionListHighlightedItemCssClass="itemHighlighted" CompletionListElementID="divCompletionListElement" />
<input type="hidden" id="hdnSelectedId" name="hdnSelectedId" value="" />
Have a javascript method to ensure selected item is captured
function GetSelectedId(source, eventArgs) {
var selectedId = eventArgs.get_value();
var e = document.getElementById('hdnSelectedId');
if (e) {
e.value = selectedId;
}
}
Create a WebMethod in your back end code that is configured in ServiceMethod property of AutoCompleteExtender
[ScriptMethod()]
[WebMethod]
public static List<string> YourWebMethod(string prefixText, int count)
{
var totalRecords = 0;
var searchResults = <<get your results here into a list or whatever container>>
//I used DataTable as a container here for searchResults
if (searchResults.Rows.Count == 0)
return new List<string>() { "No result found" };
//Create a List from your search results and return it
List<string> items = new List<string>();
foreach (DataRow searchResult in searchResults.Rows)
items.Add(AutoCompleteExtender.CreateAutoCompleteItem(searchResult["Name"].ToString(), searchResult["BuilderID"].ToString());
return items;
}
I am trying to pass a value that the ektron:MenuModelSource.TreeFilter control will use to generate the given menu. I am able to get the value from the query string
I am working on the menu solution and am stumped on what to do differently.
I am needing to set the Id for the TreeFilter property of the web server control below:
<ektron:MenuModelSource ID="menuModelSource2" runat="server">
<TreeFilter Id="355" Depth="1" />
</ektron:MenuModelSource>
I am passing a query string that looks like: ?top=355&side=375&low=123 .This way an id can be passed for each menu to be used by each designated TreeFilter on a page.
I am also able to pull in that info to the code behind file and convert it to an int for use by the TreeFilter (all of the following code is done in PageLoad):
string sideIdstr = Request.QueryString["side"];
int sideId = Convert.ToInt32(sideIdstr);
menuModelSource2.TreeFilter.Id = sideId;
However, the MenuModelSource.TreeFilter is still rendering the 355 menu rather than the 375 menu.
I can “verify” that the id has indeed been changed to 375 by using the following:
Response.Write("<h1>" + menuModelSource2.TreeFilter.Id + "</h1>");
… which shows 375 on the page.
What should I be doing instead to get the TreeFilter to use the id from the query string?
Someone suggested trying DataBind() on the server controls, but I still get the same results. Here is my current code:
protected void Page_Load(object sender, EventArgs e)
{
Ektron.Cms.API.Content.Content ContentAPI = new Ektron.Cms.API.Content.Content();
Page.Title = ContentAPI.GetContent(PageHost1.PageID).Title;
string sideIdstr = Request.QueryString["side"];
int sideId = Convert.ToInt32(sideIdstr);
menuModelSource2.TreeFilter.Id = sideId;
menuModelSource2.DataBind();
menuView2.DataBind();
Response.Write("<h1>" + menuModelSource2.TreeFilter.Id + "</h1>");
}
…and my markup is this…
<ektron:MenuModelSource ID="menuModelSource2" runat="server">
<TreeFilter Id="355" Depth="1" />
</ektron:MenuModelSource>
<ektron:MenuView ID="menuView2" runat="server" ModelSourceID="menuModelSource2">
<ListTemplate>
<ul id="menunav" runat="server" class="unstyled subnav">
<asp:PlaceHolder ID="listPlaceholder" runat="server" />
</ul>
</ListTemplate>
<ItemTemplate>
<li <%# ((Eval("Type").ToString().ToLower() == "submenu")) ? #" class=""subnav""" : #" class=""menuitem""" %>>
<asp:HyperLink ID="nodeLink" runat="server" Text='<%# Eval("Text") %>' NavigateUrl='<%# Utility.getNavigateUrl( Eval("NavigateUrl") ) %>' />
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</li>
</ItemTemplate>
</ektron:MenuView>
If anyone has a better way of doing this such as using the Ektron Framework API I would be open to that as well.
After updating the parameters of the Model source you need to call LoadData on the model source. However that method is not public, so you need to do this trick using reflection to call the method.
menuModelSource2.GetType().GetMethod("LoadData", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy).Invoke(menuModelSource2, new object[] { });
This is documented at reference.ektron.com See the aspx.cs tab. It's at the bottom.
I have a repeater like this:
<asp:Repeater runat="server" ID="pde">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<asp:Literal runat="server" ID="literal1"></asp:Literal>
</ItemTemplate>
<FooterTemplate><asp:Literal runat="server" ID="literal2"></asp:Literal></FooterTemplate>
</asp:Repeater>
Now in literal2 I want to get the value from code behind.But I am not able to get the literal2 in code behind.Any idea how to get this?
You should be able to access it by accessing the last RepeaterItem in your repeater which will be your footer. Then do a search, using FindControl, on the RepeaterItem for any control you are looking for.
Using your example above do:
Literal controlYouWant = pde.Controls[pde.Controls.Count - 1].FindControl("literal2") as Literal;
You can break down the statements to:
// This will get you the footer
RepeaterItem item = pde.Controls[pde.Controls.Count - 1];
// From here you finds any control you want within the RepeaterItem.
Literal controlYouWant = item.FindControl("literal2") as Literal;
First search through items in repeater and only take the footer item type and discard the others. Take a look to the following code.
foreach(RepeaterItem item in repeterName.Controls)
{
if (item.ItemType != ListItemType.Footer) continue;
var lblMyLabel = ((Label)item.FindControl("lblMyLabel"));
lblMyLabel.Text = "I found it!!!";
}