ASP.NET Dynamic Data Sorting on IDForeign Key - asp.net

In my application we are using ASP.NET Dynamic Data for data binding. Everything works fine.
If you see the code snipped below, it has Dynamic Field DepartmentID which is a foreign key to Department table and gets the department name from there (this is specified in DynamicData/FieldTemplates/IDForeignKey.ascx.cs).
Our requirement is to sort (order by) the records on the department name as they are visible on the grid view. The only option that I have is to sort on DepartmentID which does not serve our purpose.
How can we sort on data that is retrieved from ForeignKey?
List.aspx
<asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource" OnPreRender="GridView1_PreRender"
AllowPaging="True" AllowSorting="True" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:HyperLink ID="EditHyperLink" runat="server"
NavigateUrl='<%# table.GetActionPath(PageAction.Edit, GetDataItem()) %>'
Text="Edit" /> | <asp:LinkButton ID="DeleteLinkButton" runat="server" CommandName="Delete"
CausesValidation="false" Text="Delete"
OnClientClick='return confirm("Are you sure you want to delete this item?");'
/>
</ItemTemplate>
</asp:TemplateField>
<asp:DynamicField DataField="DepartmentID" HeaderText="Department" />
<asp:DynamicField DataField="Description" HeaderText="Description"/>
</Columns>
<PagerStyle/>
<PagerTemplate>
<asp:GridViewPager runat="server" />
</PagerTemplate>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
</div>
<asp:EntityDataSource OnSelecting="GridDataSource_Selecting" ID="GridDataSource" runat="server" EnableDelete="true" OnDeleted="GridDataSource_Deleted" >
<WhereParameters>
<asp:DynamicControlParameter ControlID="DynamicFilter1" />
</WhereParameters>
</asp:EntityDataSource>

Unfortunately it is not entirely clear from your question how are describe your metadata,
but anyway you can try to use QueryExtender control and SearchExpression class. More detail information you can find by link QueryExtender and SearchExpression with examples.
The whole idea of this is use custom LINQ.

Related

asp:EntityDataSource failing to update or delete gridview

I have a gridview of vendor bids that have foreign keys to a vendors table and a product table.
Here is my gridview and my datasource.
<table>
<asp:GridView ID="GridViewVendorBids" runat="server" AutoGenerateColumns="False"
DataSourceID="VendorBidsDS" DataKeyNames="autRecNum" ForeColor="#333333" CellPadding="4"
GridLines="None" AllowPaging="True" AllowSorting="True">
<AlternatingRowStyle BackColor="White" ForeColor="#284775" />
<Columns>
<asp:CommandField ShowEditButton="true" />
<asp:BoundField DataField="dtmBidDate" HeaderText="Bid Date" SortExpression="dtmBidDate"
DataFormatString="{0:MM/dd/yyyy}" ApplyFormatInEditMode="true" />
<asp:TemplateField HeaderText="Vendor Name" SortExpression="it.tblVendors.strVendorName">
<ItemTemplate>
<asp:Label ID="lblVendorName" runat="server" Text='<%# Eval("tblVendors.strVendorName") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlVendorList" runat="server" DataTextField="strVendorName"
DataSource='<%# getVendorList() %>' DataValueField="strVendorCode" AutoPostBack="false"
SelectedValue='<%# Bind("strVendorCode") %>' DropDownStyle="DropDownList" AutoCompleteMode="SuggestAppend"
CssClass="comboBoxInsideModalPopup" Width="250px" MaxLength="0" Style="display: inline;
top: 0px; left: 0px;" ItemInsertLocation="Append" RenderMode="Inline" Height="16px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Product Name" SortExpression="it.tblProducts.strProductName">
<ItemTemplate>
<asp:Label ID="lblProductName" runat="server" Text='<%# Eval("tblProducts.strProductName") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlProductList" runat="server" DataTextField="strProductName"
DataSource='<%# getProductList() %>' DataValueField="strProductCode" AutoPostBack="false"
SelectedValue='<%# Bind("strProductCode") %>' DropDownStyle="DropDownList" AutoCompleteMode="SuggestAppend"
CssClass="comboBoxInsideModalPopup" Width="300px" MaxLength="0" Style="display: inline;
top: 0px; left: 0px;" ItemInsertLocation="Append" RenderMode="Inline" Height="16px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Unit" SortExpression="it.tblProducts.strUnitDesc">
<ItemTemplate>
<asp:Label ID="lblUnitDesc" runat="server" Text='<%# Eval("tblProducts.strUnitDesc") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="sngBid" HeaderText="Bid" SortExpression="sngBid" ItemStyle-HorizontalAlign="Right"
DataFormatString="{0:0.00}" />
<asp:BoundField DataField="strBidType" HeaderText="Bid Type" SortExpression="strBidType"
ReadOnly="true" />
<asp:CommandField ShowDeleteButton="true" />
</Columns>
</asp:GridView>
</table>
<asp:EntityDataSource ID="VendorBidsDS" runat="server" ConnectionString="name=IMSEntities"
DefaultContainerName="IMSEntities" EntitySetName="tblVendorBid" Include="tblVendors,tblProducts"
EnableFlattening="False" OrderBy="it.dtmBidDate DESC" EnableDelete="true" EnableUpdate="true">
</asp:EntityDataSource>
When I press the update or delete key I get the following error:
No key property values were found during an update or delete operation. Check to ensure that key properties specified as binding expressions are available to the data source.
I found this post which is very similar to my problem but when I tried the answer I still get the same error.
Any help is appreciated. Thanks.
For the entity datasource you will need a primary key for the table.it allows you to change the records...After adding the primary key right click on entity datasource & select update database
Is "autRecNum" the only primary key of your VendorBidsDS Table?
You may check your Data Source Configuration whether primary key and foreign key are set properly. Also you may check if the Delete/Update Rule for FKey is set to Cascade if the other table is not updated.
And in " SelectedValue='<%# Bind("strProductCode") %>' ", "strProductCode" should be entity property instead of database column.
That's the few points I can remember from my previous project long long time ago.
Hope it can help you.
I got the "No key property values were found..." error because I was trying to save twice back to an EntityDataSource without a valid primary key. The StoreGeneratedPattern setting is correctly set to Identity and the first Insert ran correctly however the subsequent update fails - presumably because the primary key hasn't yet be set.
Basically I had manually inserted a row (using DbContext) and ran context.SaveChanges() but then my Telerik Grid translated the "Update" CommandName of the button to run another update command after the insert, causing this error. The error doesn't occur when updating existing rows, so it's very likely related to the primary key of a newly inserted row.
To solve the issue I simply set the CommandName of the button to "Cancel". My manual insert/update still runs, but then the Grid doesn't attempt another update operation and correctly closes the row I'm editing.

asp.net gridview: How can I have multiple button fields in one column?

I need to create multiple actions for a gridview - say, "Approve", "Deny", and "Return".
I can do this by creating a button field for each action:
<asp:ButtonField ButtonType="Link" CommandName="Approve" Text="Approve" />
<asp:ButtonField ButtonType="Link" CommandName="Deny" Text="Deny />
<asp:ButtonField ButtonType="Link" CommandName="Return" Text="Deny" />
However, this creates one column for each button.
Is there a way to have the same functionality, but combine them into a single column?
Have you considered using an TemplateField? Here is an example:
<asp:GridView ID="grdTest" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btnApprove" runat="server" CommandName="Approve" Text="Approve" />
<asp:LinkButton ID="btnDeny" runat="server" CommandName="Deny" Text="Deny" />
<asp:LinkButton ID="btnReturn" runat="server" CommandName="Return" Text="Return" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
You can then capture the commands the exact same way using OnRowCommand or do whatever you like. You have full control to make it behave how you need and not be bound by the built in functionality of using the regular predefined column types.
Try to put buttons into the <asp:TemplateField> instead:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton CommandName="Approve" Text="Approve" />
<asp:LinkButton CommandName="Deny" Text="Deny />
<asp:LinkButton CommandName="Return" Text="Deny" />
</ItemTemplate>
</asp:TemplateField>
The solution is not to use ButtonField elements.
To accomplish what you want you will need to create a column as a TemplateField and define buttons as regular ASP.NET <asp:Button id="myButton" /> within TemplateField's ItemTemplate or EditItemTemplate as appropriate for your UI.
You can handle Click events in the GridView_OnItemCommand() handler, where you can check e.CommandName to figure out exactly which button caused the event.

How to get cell contents in ASP.NET GridView while handling OnRowEditing?

I have a GridView with a BoundField column and quite a few item templates like the following:
<asp:GridView ID="gvUsers" runat="server" AutoGenerateColumns="False" OnRowCommand="gvUsers_RowCommand"
OnRowDataBound="gvUsers_RowDataBound" DataKeyNames="UserId" OnRowEditing="gvUsers_OnRowEditing"
OnRowUpdating="gvUsers_OnRowUpdating" OnRowUpdated="gvUsers_OnRowUpdated"
DataSourceID="DataSource1" Width="807px" Height="105px"
AllowPaging="True" >
<Columns>
<asp:BoundField DataField="UserName" HeaderText="User Name"
SortExpression="UserName" />
<asp:TemplateField HeaderText="Approver">
<ItemTemplate>
<asp:CheckBox ID="cbApprover" runat="server" Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Auditor">
<ItemTemplate>
<asp:CheckBox ID="cbAuditor" runat="server" Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btnEdit" runat="server"
CommandArgument='<%# Eval("UserName") %>' CommandName="Edit" Text="Edit" />
<asp:Label ID="lblPipe1" runat="server" Text=" | " />
<asp:LinkButton ID="btnUpdate" runat="server"
CommandArgument='<%# Eval("UserName") %>' CommandName="Update" Text="Update" />
<asp:Label ID="lblPipe" runat="server" Text=" | " />
<asp:LinkButton ID="btnDelete" runat="server"
CommandArgument='<%# Eval("UserName") %>' CommandName="Remove"
OnClientClick="return confirm('Are you sure you want to delete this user?');"
Text="Delete" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
While handling the Edit link button I need to use the value in the BoundField, UserName. Unfortunately during the OnRowEditing handler, all strings are empty "". This is also true in the ensuing OnRowDataBound handler for the row in question where e.Row.RowState == DataControlRowState.Edit. Is there a way to obtain this value after the user clicks on the Edit link, and commences the OnRowEditing event?
I arrived at a solution that was a bit more complicated than I was hoping for. I'll show code later but I did the following:
Created a HiddenField to hold the
value of the cell I wanted to edit in
its view state.
In the OnRowDataBound handler, I assigned the value to the
HiddenField.
The ItemTemplate, as seen above, sends the UserName as an
argument. I store this value in
the HiddenField.
The OnRowEditing is fired after the Command handler. That is where I
read the HiddenField.
If anyone has a simpler solution I would love hear about it.
Could it be that you're using late binding in TemplatedItems without EditItemTemplates?

Filter gridview

I have a gridview which I am binding through code behind, I want to filter the gridview based on the value given by the user in textbox.
It would be great if I'll be able to filter the gridview without any postback.
PLease help!
Thanks in advance
you could run a filter expression
<asp:sqldatasource id="articles" runat="server"
connectionstring="<%$ ConnectionStrings:aspa %>"
selectcommand="SELECT title, url, added, updated FROM aspx_articles ORDER BY title"
filterexpression="title LIKE '%{0}%' or url LIKE '%{0}%'">
<filterparameters>
<asp:controlparameter controlid="searchBox" propertyname="Text" />
</filterparameters>
</asp:sqldatasource>
or this way
Do you have a TextBox outside the GridView, and when you enter data into it and press a button, the GirdView should be filter on that data?
If so, make sure your select command can taka a parameter with the value you want to filter on. Add a ControlParameter to the SelectParameters colelction of the DataSource control (if you use a DataSource control).
Here is an example that uses the Northwind database, maybe this will help you:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="SqlDataSource1" ShowFooter="True">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False"
ReadOnly="True" SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [ProductID], [ProductName], [UnitsInStock], [UnitPrice] FROM [Alphabetical list of products] WHERE ([ProductName] LIKE '%' + #ProductName + '%')">
<SelectParameters>
<asp:ControlParameter ControlID="TextBox1" DefaultValue="%" Name="ProductName" PropertyName="Text"
Type="String" />
</SelectParameters>
</asp:SqlDataSource>
codes found here http://forums.asp.net/p/1034014/2904713.aspx
If you're using paging, I would recommend using something else (like the Microsoft Ajax Library's dataView). Because gridview paging and client-side filtering wouldn't mesh too well. But if you're not doing paging, you could do something similar to this or this.
The grid view is made for manipulation during post back. If you were to do this entirely on the client side, you'd use a JavaScript suite that would work on any table, not confined to the grid view. If it were me, I would simply use AJAX by wrapping the grid view and text box in an Update Panel. To the end user, the behavior is the same.
EDIT to include Sample code:
<asp:ScriptManager ID="ScriptManager1" AllowCustomErrorsRedirect="false" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox runat="server" ID="txtFilterString" ></asp:TextBox>
<asp:Button runat="server" ID="btnFilter" Text="FilterResults" onclick="btnFilter_Click" />
<asp:GridView runat="server" ID="grdResults"
DataKeyNames="Id"
AllowSorting="true" AllowPaging="true" PageSize="20"
PagerSettings-Mode="NumericFirstLast">
<Columns>
.....
</Columns>
</asp:GridView>
</asp:UpdatePanel>

DataBinding: 'DynamicClass1' does not contain a property with the name 'EmployeeID'

i have used aggregate function in List Page of dynamic datawebsite. When it execute it gives me,
DataBinding: 'DynamicClass1' does not contain a property with the name 'EmployeeID'.
<asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource"
AllowPaging="True" AllowSorting="True" CssClass="gridview">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:HyperLink ID="EditHyperLink" runat="server"
NavigateUrl='<%# table.GetActionPath(PageAction.Edit, GetDataItem()) %>'
Text="Edit" /> <asp:LinkButton ID="DeleteLinkButton" runat="server" CommandName="Delete"
CausesValidation="false" Text="Delete"
OnClientClick='return confirm("Are you sure you want to delete this item?");'
/> <asp:HyperLink ID="DetailsHyperLink" runat="server"
NavigateUrl='<%# table.GetActionPath(PageAction.Details, GetDataItem()) %>'
Text="Details" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle CssClass="footer"/>
<PagerTemplate>
<asp:GridViewPager runat="server" />
</PagerTemplate>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
<asp:LinqDataSource ID="GridDataSource" runat="server"
ContextTypeName="DataClassesDataContext"
TableName="Employees"
GroupBy="EmployeeNo"
Select="new(Key,
Max(Version) As VersionNo)"
EnableDelete="true">
<WhereParameters>
<asp:DynamicControlParameter ControlID="FilterRepeater" />
</WhereParameters>
</asp:LinqDataSource>
I have not changed any of the default code except i have added ContextTypeName,TableName, GroupBy and select in Linq Data source...
Table "Employees" has "EmployeeID, EmployeeNo, EmployeeName, Department, Address, City, State, Country, Version" as columns..
Any idea how to solve this?
Thanks in advance!
Regards,
Bala
The problem is that you're grouping doesn't create the type of data that the grid is expecting to receive. GetDataItem() is expecting a particular type of data and that's not what you've set up in your LinqDataSource.
Your select needs to include all the items that GetDateItem() needs, right now it doesn't:
new(Key, Max(Version) As VersionNo) //EmployeeID needs to be included here
new(Key, Max(Version) As VersionNo) is fine.
To Get the Employee... use: Key.Employee
The Key is a dynamic class containing all the properties specified in the group by statement.
Anything else (ie EmployeeNo, EmployeeName, Department, Address, City, State, Country, Version) will need an aggregate statement (ie Sum, Max, Min).

Resources