Paging not working with ListView and Webservice using Linq - asp.net

I have a simple page that looks up contacts using a webservice with a single method written in Linq. On the page, I have both a gridview and a listview with a DataPager to compare the two. I can get paging working just fine with the gridview, but the Linq code has to return all of the data on each call and let the web page pick out only a page's worth... not the best solution.
I have been told that a ListView will solve this problem, but all the examples I have been able to find have the Linq code on the web page instead of in a separate layer (e.g. a webservice). Ideally, I should be able to tell the web service to bring back a specific page worth of data (starting record number and number of rows), but how do I get the ListView (or the DataPager) to fire an event that asks for this data?
Here is the ASPX code:
<asp:ListView ID="listPersons" runat="server">
<LayoutTemplate>
<table>
<thead>
<tr>
<th>
Site ID
</th>
<th>
PersonID
</th>
<th>
Person Name
</th>
</thead>
<tbody>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</tbody>
</table>
<asp:DataPager ID="Pager1" runat="server" PagedControlID="listPersons" PageSize="5" >
<Fields>
<asp:NextPreviousPagerField ShowFirstPageButton="true" ShowPreviousPageButton="true"
ShowNextPageButton="false" ShowLastPageButton="false" />
<asp:NumericPagerField />
<asp:NextPreviousPagerField ShowFirstPageButton="false" ShowPreviousPageButton="false"
ShowNextPageButton="true" ShowLastPageButton="true" />
</Fields>
</asp:DataPager>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<%# Eval("SiteID") %>
</td>
<td>
<%# Eval("PersonID") %>
</td>
<td>
<%# Eval("PersonName") %>
</td>
</tr>
</ItemTemplate>
<EmptyDataTemplate>
No data found...
</EmptyDataTemplate>
</asp:ListView>
Here's the code behind:
private void DoList(string Match)
{
ContactsService cs = new ContactsService();
listPersons.DataSource = cs.Find(Match, 100 );
listPersons.DataBind();
}
and the web serivice:
[WebMethod]
public List<Person>Find(string Match, int Count)
{
if (Count < 5) Count = 5;
using (DataLayer.ContactsDataContext context = new ContactsDataContext())
{
var Persons =
from p in context.Persons
where p.PersonName.Contains(Match)
orderby p.LastName, p.FirstName
select new Person()
{
SiteID = p.SiteID,
PersonID = p.PersonID,
PersonName = p.PersonName,
};
return Persons.Take(Count).ToList();
}
}

Not 100% sure of an answer here. Using the DataPager while binding the DataSource at runtime will add a lot of work but I think it can be done.
Alternatively consider using either a LinqDataSource and wiring up the OnSelecting event or using an ObjectDataSource. Not sure how the DataPager works with an ODS (if at all). The LinqDataSource or the ObjectDataSource will need to be associated with the ListView using the DataSourceID.
If you must bind using the DataSource, you can wire up the OnPagePropertiesChanging event on the ListView along with the PageSize and StartRowIndex properties on the DataPager. You will need to search your control tree for your DataPager since it is likely contained in a template.

Related

how to bind memory stream to asp.net image controls with out using image url

We have a new requirement to show the signature image in result grid for each record. Currently we store the signature image as base64 format in our database .we are able to convert base 64 to memory stream.
We want to understand does any of your image control support to bind image from memory stream instead of Url .
You could keep images as base64 string form, and use data url.
The following is a example.
<asp:Image runat="server" ID="myImage" />
The code behind is
this.myImage.ImageUrl = "data:image/png;base64,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";
The premise is that you need to know all the MIME type of images.
Reference: data URIs
Sure, you can do it this way.
A gridview, listview, repeater control - they can all do this.
So markup for a grid view:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Animal" HeaderText="Animal" ItemStyle-Width="200px"/>
<asp:TemplateField HeaderText="Picture">
<ItemTemplate>
<asp:Image ID="Image1" runat="server"
Height="128px" Width="128px"
src='<%# "Data:Image/png;base64," + Eval("Image") %>'
/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And the code to load up the gridview would be:
protected void Page_Load(object sender, System.EventArgs e)
{
if (System.Web.UI.Page.IsPostBack == false)
LoadGrid();
}
public void LoadGrid()
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT Animal, Image from tblAnimals",
new SqlConnection(My.Settings.TEST4)))
{
cmdSQL.Connection.Open();
GridView1.DataSource = cmdSQL.ExecuteReader;
GridView1.DataBind();
}
}
Results:
Now I used a direct eval expression - but you could also use the ItemDataBound event of the gridview (or list view).
Also, I did hard code the "mine" type in above (assumed .png). You often might want to consider to save the file/mine type as a extra column in the database. But, if the picture types are to be all the same types - then a hard code right in the expression as per above will work fine.
If you have a lot of columns for this grid, then I tend to switch over to listview, since each column does NOT need a template, and I find for quick and dirty - grid view is ok, but listview is better for tweaking and lots of customizing. The trick is to get Visual Studio to generate the template + markup, and then blow out all templates except for item template. When you do this, then the crazy truckload of markup is reduced down to "easy" levels. And you can then with greater ease drop in controls - and you don't have template them.
So, the same listview for above would be this:
<asp:ListView ID="ListView1" runat="server">
<ItemTemplate>
<tr style="">
<td><asp:Label ID="AnimalLabel" runat="server" Text='<%# Eval("Animal") %>' /></td>
<td>
<asp:Image ID="ImageT1" runat="server"
Height="128px" Width="128px"
src='<%# "Data:Image/png;base64," + Eval("Image") %>'
/>
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0" style="">
<tr runat="server" style="">
<th runat="server" width="200">Animal</th>
<th runat="server">Image</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
So there is somewhat "more" markup, but you can with much greater ease drop in asp.net controls - and you don't have add a templatefield - (about 4 extra lines of markup for every column - so in the long run, I like the listview.
it looks quite much the same, like this:
And the behind code would be 100% the same as above.

ListView with Dynamic Controls updating all rows as contents of last row

I have a page which displays data from multiple tables in a one-to-many relationship via various FormViews and ListViews. A ListView is nested within a FormView and the correct data displays but, when I go to update, the last record in the ListView updates all rows within the ListView with its contents and I can't figure out why.
Here is some of the code:
<asp:FormView runat="server" ItemType="Table1"
DefaultMode="Edit" DataKeyNames="Table1_key"
SelectMethod="GetAll" OnItemCommand="ItemCommand"
UpdateMethod="UpdateTables" RenderOuterTable="false">
<EmptyDataTemplate>
Cannot find the Episode with Episode key <%: FriendlyUrl.Segments[0] %>
</EmptyDataTemplate>
<EditItemTemplate>
<asp:DynamicControl Mode="Edit" DataField="foo1" runat="server"/>
<asp:Button runat="server" ID="UpdateButton" CommandName="Update" Text="Update" CssClass="btn btn-primary" />
</EditItemTemplate>
<asp:ListView ID="ListView1" runat="server"
DataKeyNames="Table2_key" SelectMethod="GetTable2"
ItemType="Table2">
<ItemTemplate>
<tr>
<td>
//this doesn't update properly
<asp:DynamicControl runat="server" DataField="foo" ID="foo" Mode="Edit" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
</asp:FormView>
Update method in code-behind (which works for updating the FormView (i.e. Table1) but not the ListView content (Table2):
public void UpdateTables(int Table1_key)
{
using (_db)
{
var item = _db.Table1.Find(Table1_key);
if (item == null)
{
// The item wasn't found
ModelState.AddModelError("", String.Format("Item with id {0} was not found", Table1_key));
return;
}
TryUpdateModel(item); // this updates the foo1 property
if (ModelState.IsValid)
{
_db.SaveChanges();
}
var lesions = _db.Table2.Where(cl => cl.Table1_key == Table1_key);
foreach (var lesion in lesions)
{
TryUpdateModel(lesion); //this updates ALL the children with the value I put in the last textbox.
}
_db.SaveChanges();
}
}
I can't find anything to sort this but surely someone has wanted to do the same as me, i.e. display data from multiple tables but only have one update button for everything? Thanks!

Control placed in runat=server table sets SQL parameter at NULL on Update

I have a page with FormView and a plain html table inside. The table serves for layout and contains child controls data-bind to SqlDataSource. My problem is that if I add runat=server attribute to the table declaration, all controls inside the table set my SQL parameters at NULL in DataSource_Updating event and thus the record gets updated with NULLs instead of actual values. If I don't add runat=server, everything works fine. Sample of my code:
<asp:FormView ID="SettingsFormView" runat="server" DataKeyNames="Id" DataSourceID="SettingsDataSource"
DefaultMode="Edit" Width="560px">
<EditItemTemplate>
<strong>Settings</strong>
<table runat="server" width="350px">
<tr>
<td width="160">
Time (sec)
<dx:ASPxSpinEdit ID="textTime" runat="server"
Height="21px" Number="0" Value='<%# Bind("Time") %>' Width="104px" />
<br />
</td>
<td>
</td>
</tr>
</table>
</EditItemTemplate>
</asp:FormView>
I want to be able to remove (set invisible) some rows in code behind, that's why I need to set runat=server. However I can't get anywhere with this because SQL record updates with NULLs. Please, advice what might be wrong in my code.
Try using this.
<!-- toggle through OnLoad (can use ID as well) -->
<asp:PlaceHolder runat="server" OnLoad="MakeVisibleOrNot">
<tr>
...
</tr>
</asp:PlaceHolder>
and in the code behind:
protected void MakeVisibleOrNot(object sender, EventArgs e)
{
((Control) sender).Visible = ConfigUtil.DisplaySummaryComment;
}

How can I retrieve the value of a control within an ASP.Net Dynamic Data Custom Field Template?

Long story short, for an old project I used ASP.Net Dynamic Data and probably did a terrible job with it. One of the Field Templates has multiple controls in it, and now I need to get at the value of one control from the FormView's Submit event because we changed the way that value is stored.
I can find the Field Template itself using FindFieldTemplate... but I can't figure out how to get to the controls inside of the template.
How can I do that without re-engineering the whole thing to pull that one field out? It would probably be more correct to re-engineer it, but this is a quick fix for a website that's going to be scrapped in a couple months.
EDIT: Was asked to show code so here it is. The FormView is pretty standard, just uses an . The Field Template actually has it's own listview and I'm controlling it's mode in codebehind. But I need to get the value of txtTitle.
Ticket_TicketMemo.ascx:
<asp:ListView ID="lvTicketMemos" DataSourceID="ldsTicketMemo"
InsertItemPosition="FirstItem" OnLoad="lvTicketMemo_Load" runat="server">
<LayoutTemplate>
<div style="overflow:auto; height:125px; width:600px;">
<table class="ListViewTable" runat="server">
<tr id="itemPlaceHolder" runat="server" />
</table>
</div>
</LayoutTemplate>
<ItemTemplate>
<tr valign="top" class='<%# Container.DataItemIndex % 2 == 0 ? "" : "Alternate" %>'>
<td><asp:DynamicControl ID="dcType" DataField="Type" runat="server" /></td>
<td><asp:DynamicControl ID="dcMemo" DataField="Memo" runat="server" /></td>
<td><asp:DynamicControl ID="dcCreateTime" DataField="CreateTime" runat="server" /></td>
</tr>
</ItemTemplate>
<InsertItemTemplate>
<tr valign="top">
<td colspan="3">
<asp:TextBox ID="txtTitle" Width="99%" Visible="false" OnLoad="txtTitle_Load" runat="server" /><br /><br />
</td>
</tr>
<tr valign="top">
<td colspan="3" width="600px">
<asp:TextBox ID="txtMemo" Text='<%# Bind("Memo") %>' Width="99%" OnLoad="txtMemo_Load" TextMode="MultiLine"
Rows="5" runat="server" />
<asp:RequiredFieldValidator ID="rfvMemo" Text="Must enter notes" ControlToValidate="txtMemo" runat="server" />
</td>
</tr>
</InsertItemTemplate>
I have just simulated your problem in my Dynamic Data project. Based on my research (and search) in order to get control value (not from DynamicControl value) in Dynamic Data you should implement the following method (i am using this method in my project and i have found one on Steve blog, i don't remember full link):
/// <summary>
/// Get the control by searching recursively for it.
/// </summary>
/// <param name="Root">The control to start the search at.</param>
/// <param name="Id">The ID of the control to find</param>
/// <returns>The control the was found or NULL if not found</returns>
public static Control FindControlRecursive(this Control Root, string Id)
{
if (Root.ClientID.IndexOf(Id) > 0)
return Root;
foreach (Control Ctl in Root.Controls)
{
Control FoundCtl = FindControlRecursive(Ctl, Id);
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
Now, my EXAMPLE.
First, my custom Insert.aspx page with FormView and EntityDataSource:
<asp:FormView runat="server" ID="FormView1" DataSourceID="DetailsDataSource" DefaultMode="Insert"
OnItemCommand="FormView1_ItemCommand" RenderOuterTable="false">
<InsertItemTemplate>
<table>
<tr valign="top">
<td colspan="3">
<asp:TextBox ID="txtTitle" Width="99%" Visible="true" runat="server" /><br />
<br />
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>
<asp:EntityDataSource ID="DetailsDataSource" runat="server" EnableInsert="true" OnInserted="DetailsDataSource_Inserted" />
Then, Inserted event of EntityDataSource:
protected MetaTable table;
protected void DetailsDataSource_Inserted(object sender, EntityDataSourceChangedEventArgs e)
{
if (e.Exception == null || e.ExceptionHandled)
{
string strTitle = String.Empty;
Control CtlTitle = FormView1.FindControlRecursive("txtTitle");
if (CtlTitle != null)
{
TextBox TextBoxTitle = (TextBox)CtlTitle;
strTitle = TextBoxTitle.Text;
}
Response.Redirect(table.ListActionPath + "?" + "Department_Id=" + strTitle);
}
}
Finally, i enter the text into txtTitle, for example, 13 and then i get

How to dynamically assign datasource to listview

I am having a problem with dynamically assigning datasource to listview.
For example I have list of receivedBonuses(Bonus), receivedLeaves(Leave) and I want listview to display those list items depending on what link button user clicked.
Researching internet and stackoverflow.com i found 3 solutions:
Using repeater inside the listview. But in my case, I could not apply it to my case and i got totally confused
Using nested listviews. I tried to do like this:
<asp:ListView ID = "bonuses" runat="server" DataSource ='<%# Eval("received_bonuses") %>' >
<ItemTemplate>
<tr>
<td><%# Eval("bonus_desc")%></td>
<td><%# Eval("bonus_type")%></td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table>
<tr>
<th>Bonus Description</th>
<th>Bonus Received Date</th>
</tr>
<tr ID="itemPlaceholder" runat="server" />
</table>
</LayoutTemplate>
<table>
<tr>
<th>Bonus Description</th>
<th>Bonus Received Date</th>
</tr>
<tr ID="itemPlaceholder" runat="server" />
</table>
</LayoutTemplate>
</asp:ListView>
<br />
and on back code I tried to write like this:
protected void dataBound(object sender, ListViewItemEventArgs e)
{
this.DataBindChildren();
}
It didn't give any errors it just didn't work.
Using data pager
I have no idea how to apply it to my case.
Any help is appreciated.
Thanks a lot.
All you have to do on the server side is change the DataSource or DataSourceID property and call DataBind on the ListView.
You have to make sure when using <%# Eval("") %> syntax that the objects you are binding to have those properties that are named in the Eval. So you may have a problem with with switching datasources when your properties are prepended with the typename and underscore.
That being said. There are 2 options you have an changing a data source. In the click event of the button or whatever switching mechanism you are using you can just write something like.
Not using a DataSource in the markup:
List<Bonus> bonusList = GetBonuses();
MyListView.DataSource = bonusList;
MyListView.DataBind();
Using a DataSource in the markup:
//where bonus list would be the id of the datasource in the markup
MyListView.DataSourceID= "BonusList";
MyListView.DataBind();
Do you need to do this dynamically? If you only have "bonuse" and "leave" can you not create two listviews and then just do display logic to visible=true/false the listview based upon the link button clicked?

Resources