- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
FormView and LLBLGenProDataSource2
Joined: 23-Jan-2005
I'm looking for some suggestions on working with LLBLGenProDataSource2 and ASP.NET 2.0 FormView. If the form and the entity match up, life is simple. However, in most of my tables, at least one field is a foreign key, typically an integer. In the ItemTemplate, this can be represented by a dropdown list which displays a related string value.
My problem is that the ItemTemplate shows the "unfriendly" integer value. I'd like to know how other people are handling this.
Frans, I'd like to see a few some ASP.NET examples that do something other than just retrieve the data. Updating, inserting and deleting examples have been hard for me to find.
Using insert/update parameters. You've the customers in a dropdownlist for example and in the datasource for the formview, you specify an insertparameter / updateparameter (if you want it to be updatable ) which obtains its value from the dropdownlist control. You then don't specify the FK field.
Here's an example.
Add an order to the customer:
<asp:DropDownList ID="_customerComboBox" runat="server" AutoPostBack="True" DataSourceID="_customersDS" DataTextField="CustomerId" DataValueField="CustomerId">
</asp:DropDownList><br />
<cc1:LLBLGenProDataSource2 ID="_customersDS" runat="server" AdapterTypeName="NWTest.DatabaseSpecific.DataAccessAdapter, NWTestDBSpecific" DataContainerType="EntityCollection" EntityFactoryTypeName="NWTest.FactoryClasses.CustomersEntityFactory, NWTest">
</cc1:LLBLGenProDataSource2>
<br />
Current orders:
<br />
<asp:GridView ID="_ordersGrid" runat="server" AutoGenerateColumns="False" DataKeyNames="OrderId" DataSourceID="_ordersDS" OnSelectedIndexChanged="_ordersGrid_SelectedIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="OrderId" HeaderText="OrderId" ReadOnly="True" SortExpression="OrderId" />
<asp:BoundField DataField="CustomerId" HeaderText="CustomerId" SortExpression="CustomerId" />
<asp:BoundField DataField="ShipName" HeaderText="ShipName" SortExpression="ShipName" />
<asp:BoundField DataField="ShipAddress" HeaderText="ShipAddress" SortExpression="ShipAddress" />
<asp:BoundField DataField="ShipCity" HeaderText="ShipCity" SortExpression="ShipCity" />
<asp:BoundField DataField="ShipRegion" HeaderText="ShipRegion" SortExpression="ShipRegion" />
<asp:BoundField DataField="ShipPostalCode" HeaderText="ShipPostalCode" SortExpression="ShipPostalCode" />
<asp:BoundField DataField="ShipCountry" HeaderText="ShipCountry" SortExpression="ShipCountry" />
<asp:BoundField DataField="EmployeeId" HeaderText="EmployeeId" SortExpression="EmployeeId" />
<asp:BoundField DataField="OrderDate" HeaderText="OrderDate" SortExpression="OrderDate" />
<asp:BoundField DataField="RequiredDate" HeaderText="RequiredDate" SortExpression="RequiredDate" />
<asp:BoundField DataField="ShippedDate" HeaderText="ShippedDate" SortExpression="ShippedDate" />
<asp:BoundField DataField="Freight" HeaderText="Freight" SortExpression="Freight" />
<asp:BoundField DataField="ShipVia" HeaderText="ShipVia" SortExpression="ShipVia" />
</Columns>
</asp:GridView>
<cc1:LLBLGenProDataSource2 ID="_ordersDS" runat="server" AdapterTypeName="NWTest.DatabaseSpecific.DataAccessAdapter, NWTestDBSpecific" DataContainerType="EntityCollection" EntityFactoryTypeName="NWTest.FactoryClasses.OrdersEntityFactory, NWTest">
<SelectParameters>
<asp:ControlParameter ControlID="_customerComboBox" Name="CustomerId" PropertyName="SelectedValue" />
</SelectParameters>
<InsertParameters>
<asp:ControlParameter ControlID="_customerComboBox" Name="CustomerId" PropertyName="SelectedValue" />
</InsertParameters>
</cc1:LLBLGenProDataSource2>
<br />
<br />
New order form<asp:FormView ID="_newOrderFormView" runat="server" DataKeyNames="OrderId" DataSourceID="_ordersDS">
<EditItemTemplate>
OrderId:
<asp:Label ID="OrderIdLabel1" runat="server" Text='<%# Eval("OrderId") %>'></asp:Label><br />
EmployeeId:
<asp:TextBox ID="EmployeeIdTextBox" runat="server" Text='<%# Bind("EmployeeId") %>'>
</asp:TextBox><br />
OrderDate:
<asp:TextBox ID="OrderDateTextBox" runat="server" Text='<%# Bind("OrderDate") %>'>
</asp:TextBox><br />
RequiredDate:
<asp:TextBox ID="RequiredDateTextBox" runat="server" Text='<%# Bind("RequiredDate") %>'>
</asp:TextBox><br />
ShippedDate:
<asp:TextBox ID="ShippedDateTextBox" runat="server" Text='<%# Bind("ShippedDate") %>'>
</asp:TextBox><br />
ShipVia:
<asp:TextBox ID="ShipViaTextBox" runat="server" Text='<%# Bind("ShipVia") %>'>
</asp:TextBox><br />
Freight:
<asp:TextBox ID="FreightTextBox" runat="server" Text='<%# Bind("Freight") %>'>
</asp:TextBox><br />
ShipName:
<asp:TextBox ID="ShipNameTextBox" runat="server" Text='<%# Bind("ShipName") %>'>
</asp:TextBox><br />
ShipAddress:
<asp:TextBox ID="ShipAddressTextBox" runat="server" Text='<%# Bind("ShipAddress") %>'>
</asp:TextBox><br />
ShipCity:
<asp:TextBox ID="ShipCityTextBox" runat="server" Text='<%# Bind("ShipCity") %>'>
</asp:TextBox><br />
ShipRegion:
<asp:TextBox ID="ShipRegionTextBox" runat="server" Text='<%# Bind("ShipRegion") %>'>
</asp:TextBox><br />
ShipPostalCode:
<asp:TextBox ID="ShipPostalCodeTextBox" runat="server" Text='<%# Bind("ShipPostalCode") %>'>
</asp:TextBox><br />
ShipCountry:
<asp:TextBox ID="ShipCountryTextBox" runat="server" Text='<%# Bind("ShipCountry") %>'>
</asp:TextBox><br />
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update" Text="Update">
</asp:LinkButton>
<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel">
</asp:LinkButton>
</EditItemTemplate>
<InsertItemTemplate>
OrderId:
<asp:TextBox ID="OrderIdTextBox" runat="server" Text='<%# Bind("OrderId") %>'>
</asp:TextBox><br />
EmployeeId:
<asp:TextBox ID="EmployeeIdTextBox" runat="server" Text='<%# Bind("EmployeeId") %>'>
</asp:TextBox><br />
OrderDate:
<asp:TextBox ID="OrderDateTextBox" runat="server" Text='<%# Bind("OrderDate") %>'>
</asp:TextBox><br />
RequiredDate:
<asp:TextBox ID="RequiredDateTextBox" runat="server" Text='<%# Bind("RequiredDate") %>'>
</asp:TextBox><br />
ShippedDate:
<asp:TextBox ID="ShippedDateTextBox" runat="server" Text='<%# Bind("ShippedDate") %>'>
</asp:TextBox><br />
ShipVia:
<asp:TextBox ID="ShipViaTextBox" runat="server" Text='<%# Bind("ShipVia") %>'>
</asp:TextBox><br />
Freight:
<asp:TextBox ID="FreightTextBox" runat="server" Text='<%# Bind("Freight") %>'>
</asp:TextBox><br />
ShipName:
<asp:TextBox ID="ShipNameTextBox" runat="server" Text='<%# Bind("ShipName") %>'>
</asp:TextBox><br />
ShipAddress:
<asp:TextBox ID="ShipAddressTextBox" runat="server" Text='<%# Bind("ShipAddress") %>'>
</asp:TextBox><br />
ShipCity:
<asp:TextBox ID="ShipCityTextBox" runat="server" Text='<%# Bind("ShipCity") %>'>
</asp:TextBox><br />
ShipRegion:
<asp:TextBox ID="ShipRegionTextBox" runat="server" Text='<%# Bind("ShipRegion") %>'>
</asp:TextBox><br />
ShipPostalCode:
<asp:TextBox ID="ShipPostalCodeTextBox" runat="server" Text='<%# Bind("ShipPostalCode") %>'>
</asp:TextBox><br />
ShipCountry:
<asp:TextBox ID="ShipCountryTextBox" runat="server" Text='<%# Bind("ShipCountry") %>'>
</asp:TextBox><br />
<asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert" Text="Insert">
</asp:LinkButton>
<asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel">
</asp:LinkButton>
</InsertItemTemplate>
<ItemTemplate>
OrderId:
<asp:Label ID="OrderIdLabel" runat="server" Text='<%# Eval("OrderId") %>'></asp:Label><br />
CustomerId:
<asp:Label ID="CustomerIdLabel" runat="server" Text='<%# Bind("CustomerId") %>'></asp:Label><br />
EmployeeId:
<asp:Label ID="EmployeeIdLabel" runat="server" Text='<%# Bind("EmployeeId") %>'></asp:Label><br />
OrderDate:
<asp:Label ID="OrderDateLabel" runat="server" Text='<%# Bind("OrderDate") %>'></asp:Label><br />
RequiredDate:
<asp:Label ID="RequiredDateLabel" runat="server" Text='<%# Bind("RequiredDate") %>'></asp:Label><br />
ShippedDate:
<asp:Label ID="ShippedDateLabel" runat="server" Text='<%# Bind("ShippedDate") %>'></asp:Label><br />
ShipVia:
<asp:Label ID="ShipViaLabel" runat="server" Text='<%# Bind("ShipVia") %>'></asp:Label><br />
Freight:
<asp:Label ID="FreightLabel" runat="server" Text='<%# Bind("Freight") %>'></asp:Label><br />
ShipName:
<asp:Label ID="ShipNameLabel" runat="server" Text='<%# Bind("ShipName") %>'></asp:Label><br />
ShipAddress:
<asp:Label ID="ShipAddressLabel" runat="server" Text='<%# Bind("ShipAddress") %>'></asp:Label><br />
ShipCity:
<asp:Label ID="ShipCityLabel" runat="server" Text='<%# Bind("ShipCity") %>'></asp:Label><br />
ShipRegion:
<asp:Label ID="ShipRegionLabel" runat="server" Text='<%# Bind("ShipRegion") %>'></asp:Label><br />
ShipPostalCode:
<asp:Label ID="ShipPostalCodeLabel" runat="server" Text='<%# Bind("ShipPostalCode") %>'></asp:Label><br />
ShipCountry:
<asp:Label ID="ShipCountryLabel" runat="server" Text='<%# Bind("ShipCountry") %>'></asp:Label><br />
<asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit">
</asp:LinkButton>
<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete">
</asp:LinkButton>
<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New" Text="New">
</asp:LinkButton>
</ItemTemplate>
</asp:FormView>
Joined: 23-Jan-2005
Perhaps I didn't ask my question clearly. I was actually trying to solve a display (retrieval/select) problem but was also commenting that I haven't seen much in the way of examples for insert/update/delete.
I have mostly solved my original question but I'm not sure if my solution is the best way. This post is based on the Northwind database to make it easy for anyone to test or respond.
To re-state my question: Using a FormView, it is often true that the display elements (ItemTemplate) might come from several tables. For example, when showing product information, I'd like to show the CompanyName from the Suppliers table rather than the SupplierID foreign key value in the Products table. In the EditTemplate or the InsertTemplate, this can be done by using dropdownlists.
My solution (so far): I created a typedlist (ProductExtended) of the fields in the Products table plus the CompanyName and the CategoryName from the Suppliers and Categories tables.
I'm using the formview_modeChanging event to switch the datasource between the typedList (readonly) for the ItemTemplate view and the ProductEntity for the EditTemplate and InsertTemplate.
The complete code is below. (In an effort to make it completely portable, I put everything in the page. Normally I would have master page, content page css file and code file to create this)
What I'd like to have are any comments on this approach and any suggestions for alternative approaches. I'm still trying to figure out two other things: 1) How can I retrieve the identity value for new rows? 2) How can I get the entity/typedlist row for the current record? I'd like to get values from the entity and display them in a section header on the page. As an example, get the product name and display it on the top of the page.
As always, any help would be appreciated.
<%@ Page Language="VB" %>
<%@ Register Assembly="SD.LLBLGen.Pro.ORMSupportClasses.NET20" Namespace="SD.LLBLGen.Pro.ORMSupportClasses"
TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'set initial filter for datasource control.
setDataSource(FormViewMode.ReadOnly)
End If
End Sub
Protected Sub formData_ModeChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewModeEventArgs) Handles formData.ModeChanging
' Use the NewMode property to determine which mode the
' FormView control is changing into.
setDataSource(e.NewMode)
End Sub
Sub setDataSource(ByVal mode As FormViewMode)
Trace.Warn("set datasource")
Dim id As Integer = Convert.ToInt32(Request.Params("id"))
Dim bucket As New RelationPredicateBucket
Dim filter As New PredicateExpression
Select Case mode
Case FormViewMode.ReadOnly
'item template needs to show a "friendly" value for the
'foreign key fields. use a list/typed view as the datasource
With dsProduct
.AdapterTypeName = "DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
'for a typedview
'.DataContainerType = DataSourceDataContainerType.TypedView
'.TypedViewTypeName = "DMS.Northwind.DAL.TypedViewClasses.ProductBaseTypedView, DMS.Northwind.DAL"
'for a typedlist
.DataContainerType = DataSourceDataContainerType.TypedList
.TypedListTypeName = "DMS.Northwind.DAL.TypedListClasses.ProductExtendedTypedList, DMS.Northwind.DAL"
End With
'filter.Add(ProductBaseFields.ProductId = id)
filter.Add(ProductFields.ProductId = id)
Case FormViewMode.Edit, FormViewMode.Insert
'edit and insert modes just use the entity
'foreign keys are shown in the UI via lists
With dsProduct
.AdapterTypeName = "DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
.DataContainerType = DataSourceDataContainerType.EntityCollection
.EntityFactoryTypeName = "DMS.Northwind.DAL.FactoryClasses.ProductEntityFactory, DMS.Northwind.DAL"
End With
filter.Add(ProductFields.ProductId = id)
End Select
dsProduct.FilterToUse = New RelationPredicateBucket(filter)
End Sub
Protected Sub formData_ItemInserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewInsertEventArgs) Handles formData.ItemInserting
e.Values.Add("LastUpdate", DateTime.Now)
e.Values.Add("Discontinued", True)
End Sub
Protected Sub formData_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewUpdateEventArgs) Handles formData.ItemUpdating
If e.NewValues.Contains("LastUpdate") Then
e.NewValues.Remove("LastUpdate")
End If
e.NewValues.Add("LastUpdate", DateTime.Now)
End Sub
Protected Sub dsProduct_PerformSelect(ByVal sender As Object, ByVal e As SD.LLBLGen.Pro.ORMSupportClasses.PerformSelectEventArgs2) Handles dsProduct.PerformSelect
Trace.Warn("perform select")
Trace.Warn(e.DataContainerType.ToString)
'Select Case e.DataContainerType
' Case DataSourceDataContainerType.EntityCollection
' Dim row As ProductEntity = DirectCast(e.ContainedCollection, ProductEntity)
' Me.litSubHeader.Text = row.ProductName
' Case DataSourceDataContainerType.TypedList
' Dim list As ProductExtendedTypedList = DirectCast(e.ContainedTypedList, ProductExtendedTypedList)
'End Select
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Product List</title>
<style type="text/css">
h1,h2,h3,h4,h5
{
color: #003366;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-weight: 700;
font-style: normal;
text-decoration: none;
word-spacing: normal;
letter-spacing: normal;
text-transform: none;
}
h1 {
font-size: 1.15em;
}
h2 {
font-size: 1em;
}
img {
margin-top: 5px;
margin-left: 10px;
margin-right: 10px;
border: 0px;
}
th.dataLabel, td.dataLabel {
font-family:Arial, Helvetica, sans-serif;
font-weight:bold;
font-size: 0.75em;
color: #000084;
text-align: right;
vertical-align: top;
}
td.dataCell {
font-family: Arial, Helvetica, sans-serif;
font-weight:bold;
font-size: 0.75em;
vertical-align: top;
}
.gridHeader
{
font-family: Arial, Helvetica, sans-serif;
font-weight:bold;
font-size:9pt;
vertical-align: top;
text-align:left;
background-color: #ffffff;
color: #000000;
/*
background-color: #4A3C8C;
color:#F7F7F7;
*/
}
.gridFooter
{
font-family: Arial, Helvetica, sans-serif;
font-size:9pt;
vertical-align: top;
/* background-color: #b5c7de; */
background-color: #D7D7D7;
color:#4A3C8C;
border-top-color:Black;
border-top-width:1px;
border-top-style:solid;
}
.gridItem
{
font-family: Arial, Helvetica, sans-serif;
font-size:8pt;
vertical-align: top;
background-color: #e7e7ff;
color:#4A3C8C;
}
.gridItemAlternate{
font-family: Arial, Helvetica, sans-serif;
font-size:8pt;
vertical-align: top;
background-color: #f7f7f7;
color:#4A3C8C;
}
.gridItemSelected
{
font-size: 8pt;
vertical-align: top;
font-family: Arial, Helvetica, sans-serif;
background-color: #cedbe2;
}
.gridItemEdit
{
font-family: Arial, Helvetica, sans-serif;
font-size:8pt;
vertical-align: top;
background-color: #d7d7d7;
}
tr.gridPager
{
font-family: Arial, Helvetica, sans-serif;
font-size:8pt;
vertical-align: top;
background-color: #E7E7FF;
color: #4A3C8C;
}
.fieldLabelSmall {
font-family: "Times New Roman", Times, serif;
font-size: 9pt;
color: teal;
}
.validationSmall {
font-family: "Times New Roman", Times, serif;
font-size: 9pt;
color: red;
}
div#mainContent
{
/*
top:125px;
position:absolute;
clear:both;
*/
width: 75%;
border: 0px solid navy;
margin: 1em 1em 1em 150px;
padding: 0;
/*float:right;*/
}
div#sideBar
{
top:175px;
left:5px;
position:absolute;
margin:1em 1em 1em 5px;
padding: 0;
background:white;
width:100px;
border: 1px solid navy;
float:left;
font-size: 1em;
}
div#sideBar ul {margin-left: 0em; padding-left: 2px;}
div#sideBar li
{
list-style-type:none;
list-style-position:outside;
font-size:0.80em;
}
div#sideBar a
{
display:block;
padding:4px 8px;
margin:0;
color:black;
text-decoration:none;
text-align:left;
}
div#sideBar a:hover
{
background-color: #e7e7ff;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div id="top" align="center">
<h1 >
<asp:image id="imgLogo" runat="server" imageurl="~/images/northwind.gif" imagealign="Left">
</asp:image>
<asp:literal id="litPageHeader" runat="server" text="Product Detail"></asp:literal></h1>
<h2><asp:literal id="litSubHeader" runat="server"></asp:literal></h2>
<asp:Label ID="lblMessage" runat="server" /><br />
</div>
<div id="sideBar">
<ul>
<li><asp:HyperLink id="lnkHome" runat="server" NavigateUrl="~/default.aspx" Text="Home" /></li>
<li><asp:HyperLink id="lnkProductList" runat="server" NavigateUrl="productlist.aspx" Text="Product List" /></li>
</ul>
</div>
<div id="mainContent">
<asp:FormView ID="formData" runat="server" DataKeyNames="ProductId"
DataSourceID="dsProduct" OnItemUpdating="formData_ItemUpdating">
<EditItemTemplate>
<table width="500" >
<tr>
<td align="right" class="dataLabel" style="width: 150px">
Product Id</td>
<td align="left" class="dataCell">
<asp:Label ID="ProductIdLabel1" runat="server" Text='<%# Eval("ProductId") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Product Name</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ProductNameTextBox" runat="server" Text='<%# Bind("ProductName") %>'>
</asp:TextBox><asp:RequiredFieldValidator ID="vreqProductName" runat="server" ControlToValidate="ProductNameTextBox"
ErrorMessage="Required" Display="Dynamic" ></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Supplier</td>
<td align="left" class="dataCell">
<asp:DropDownList ID="ddlSupplierID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsSupplier"
DataTextField="CompanyName"
DataValueField="SupplierId"
SelectedValue='<%# Bind("SupplierID") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="vreqSupplier" runat="server" ControlToValidate="ddlSupplierID"
ErrorMessage="Required" InitialValue="-1" Display="Dynamic" ></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Category
</td>
<td align="left" class="dataCell">
<asp:DropDownList ID="ddlCategoryID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsCategory"
DataTextField="CategoryName"
DataValueField="CategoryID"
SelectedValue='<%# Bind("CategoryId") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="vreqCategoryID" runat="server" ControlToValidate="ddlCategoryID"
Display="Dynamic" ErrorMessage="Required" InitialValue="-1"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Quantity Per Unit</td>
<td align="left" class="dataCell">
<asp:TextBox ID="QuantityPerUnitTextBox" runat="server" Text='<%# Bind("QuantityPerUnit") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqQuantityPerUnit" runat="server" ControlToValidate="QuantityPerUnitTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Unit Price</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitPriceTextBox" runat="server" Text='<%# Bind("UnitPrice") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitPrice" runat="server" ControlToValidate="UnitPriceTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitPrice" runat="server" ControlToValidate="UnitPriceTextBox"
Display="Dynamic" ErrorMessage="Must be > 0" Operator="GreaterThan" Type="Currency"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units In Stock
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsInStockTextBox" runat="server" Text='<%# Bind("UnitsInStock") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitsInStock" runat="server" ControlToValidate="UnitsInStockTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitsInStock" runat="server" ControlToValidate="UnitsInStockTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units On Order
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsOnOrderTextBox" runat="server" Text='<%# Bind("UnitsOnOrder") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitsOnOrder" runat="server" ControlToValidate="UnitsOnOrderTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitsOnOrder" runat="server" ControlToValidate="UnitsOnOrderTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Reorder Level</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ReorderLevelTextBox" runat="server" Text='<%# Bind("ReorderLevel") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqReorderLevel" runat="server" ControlToValidate="ReorderLevelTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomReorderLevel" runat="server" ControlToValidate="ReorderLevelTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Discontinued</td>
<td align="left" class="dataCell">
<asp:CheckBox ID="DiscontinuedCheckBox" runat="server" Checked='<%# Bind("Discontinued") %>' /></td>
</tr>
<%--
<tr>
<td align="right" class="dataLabel" >
Last Update</td>
<td align="left" class="dataCell">
<asp:TextBox ID="LastUpdateTextBox" runat="server" Text='< %# Bind("LastUpdate") % >'>
</asp:TextBox></td>
</tr>
--%>
<tr>
<td align="right" class="dataLabel">
</td>
<td align="left" class="dataCell">
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
Text="Update">
</asp:LinkButton>
<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel"
Text="Cancel">
</asp:LinkButton></td>
</tr>
</table>
</EditItemTemplate>
<InsertItemTemplate>
<table width="500" >
<tr>
<td align="right" class="dataLabel" style="width: 182px" >
Product Name</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ProductNameTextBox" runat="server" Text='<%# Bind("ProductName") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqProductName" runat="server" ErrorMessage="Required"
ControlToValidate ="ProductNameTextBox"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px" >
Supplier</td>
<td align="left" class="dataCell">
<asp:DropDownList ID="ddlSupplierID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsSupplier"
DataTextField="CompanyName"
DataValueField="SupplierId"
SelectedValue='<%# Bind("SupplierId") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="vreqSupplier" runat="server"
ErrorMessage="Required" ControlToValidate="ddlSupplierID" InitialValue="-1"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px; height: 24px" >
Category
</td>
<td align="left" class="dataCell" style="height: 24px">
<asp:DropDownList ID="ddlCategoryID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsCategory"
DataTextField="CategoryName"
DataValueField="CategoryID"
SelectedValue='<%# Bind("CategoryId") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px" >
Quantity Per Unit</td>
<td align="left" class="dataCell">
<asp:TextBox ID="QuantityPerUnitTextBox" runat="server" Text='<%# Bind("QuantityPerUnit") %>'>
</asp:TextBox></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px" >
Unit Price</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitPriceTextBox" runat="server" Text='<%# Bind("UnitPrice") %>'>
</asp:TextBox></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px" >
Units In Stock
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsInStockTextBox" runat="server" Text='<%# Bind("UnitsInStock") %>'>
</asp:TextBox></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px" >
Units On Order
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsOnOrderTextBox" runat="server" Text='<%# Bind("UnitsOnOrder") %>'>
</asp:TextBox></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px" >
Reorder Level</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ReorderLevelTextBox" runat="server" Text='<%# Bind("ReorderLevel") %>'>
</asp:TextBox></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="width: 182px">
</td>
<td align="left" class="dataCell">
<asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert"
Text="Insert">
</asp:LinkButton>
<asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel"
Text="Cancel">
</asp:LinkButton>
</td>
</tr>
</table>
</InsertItemTemplate>
<ItemTemplate>
<table width="500" >
<tr>
<td align="right" class="dataLabel" style="width: 150px">
Product Id</td>
<td align="left" class="dataCell" >
<asp:Label ID="ProductIdLabel" runat="server" Text='<%# Eval("ProductId") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Product Name
</td>
<td align="left" class="dataCell" >
<asp:Label ID="ProductNameLabel" runat="server" Text='<%# Bind("ProductName") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Supplier</td>
<td align="left" class="dataCell" >
<asp:Label ID="SupplierIdLabel" runat="server" Text='<%# Bind("CompanyName") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Category</td>
<td align="left" class="dataCell" >
<asp:Label ID="CategoryIdLabel" runat="server" Text='<%# Bind("CategoryName") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Quantity Per Unit
</td>
<td align="left" class="dataCell" >
<asp:Label ID="QuantityPerUnitLabel" runat="server" Text='<%# Bind("QuantityPerUnit") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Unit Price</td>
<td align="left" class="dataCell" >
<asp:Label ID="UnitPriceLabel" runat="server" Text='<%# Bind("UnitPrice") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units In Stock</td>
<td align="left" class="dataCell" >
<asp:Label ID="UnitsInStockLabel" runat="server" Text='<%# Bind("UnitsInStock") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="height: 18px" >
Units On Order
</td>
<td align="left" class="dataCell" style="height: 18px" >
<asp:Label ID="UnitsOnOrderLabel" runat="server" Text='<%# Bind("UnitsOnOrder") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Reorder Level</td>
<td align="left" class="dataCell" >
<asp:Label ID="ReorderLevelLabel" runat="server" Text='<%# Bind("ReorderLevel") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Discontinued
</td>
<td align="left" class="dataCell" >
<asp:CheckBox ID="DiscontinuedCheckBox" runat="server" Checked='<%# Bind("Discontinued") %>'
Enabled="false" /></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Last Update</td>
<td align="left" class="dataCell" >
<asp:Label ID="LastUpdateLabel" runat="server" Text='<%# Bind("LastUpdate") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
</td>
<td align="left" class="dataCell" >
<br />
<asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit"
Text="Edit"></asp:LinkButton>
<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete"
Text="Delete"></asp:LinkButton>
<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New"
Text="New"></asp:LinkButton>
</td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>
</div>
<cc1:LLBLGenProDataSource2 ID="dsProduct" runat="server"
AdapterTypeName="DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
DataContainerType="TypedList" TypedListTypeName="DMS.Northwind.DAL.TypedListClasses.ProductExtendedTypedList, DMS.Northwind.DAL" LivePersistence="false" >
</cc1:LLBLGenProDataSource2>
<cc1:LLBLGenProDataSource2 ID="dsSupplier" runat="server" AdapterTypeName="DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
DataContainerType="EntityCollection" EntityFactoryTypeName="DMS.Northwind.DAL.FactoryClasses.SupplierEntityFactory, DMS.Northwind.DAL">
</cc1:LLBLGenProDataSource2>
<cc1:LLBLGenProDataSource2 ID="dsCategory" runat="server" AdapterTypeName="DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
DataContainerType="EntityCollection" EntityFactoryTypeName="DMS.Northwind.DAL.FactoryClasses.CategoryEntityFactory, DMS.Northwind.DAL">
</cc1:LLBLGenProDataSource2>
</form>
</body>
</html>
My solution (so far): I created a typedlist (ProductExtended) of the fields in the Products table plus the CompanyName and the CategoryName from the Suppliers and Categories tables.
I'm using the formview_modeChanging event to switch the datasource between the typedList (readonly) for the ItemTemplate view and the ProductEntity for the EditTemplate and InsertTemplate.
For viewing I'd suggest you use a ProductEntity that has 2 extra fields (CompanyName and the CategoryName -> you may use the designer to add fields mapped on related fields) and use PrefetchPaths to fetch those fields while you are fetching the ProductEntity.
Joined: 23-Jan-2005
Can you provide a short code example?
I tried this:
With datasourceGrid 'the LLBLGenDatasource
.PrefetchPathToUse.Add(ProductEntity.PrefetchPathCategories)
.PrefetchPathToUse.Add(ProductEntity.PrefetchPathSuppliers)
End With
That gets me a null reference exception so I guess I need to instantiate something but I'm not clear on what that should be.
Edit:
Looking at the method, it looks like this is only available for TypedList/TypedView. So how do I use PrefetchPath with the LLBLGenDatasource?
jovball wrote:
Am I correct that the PrefetchPathToAdd is not available for EntityCollections? If so, I'm still looking for a solution for this problem.
Prefetch paths are used for collections, it's not used in typedview/typedlist scenario's obviously.
It's not set to a value so your code fails, because it will first do a get on the property which will return null/Nothing. So do as Jessynoo says: create the prefetchpath object first, then set the property
Joined: 23-Jan-2005
OK, I'm 90% of the way there. I can only hope that the last mile (km * 1.60934 for you Frans ) is not the hardest.
The PerformXX events look like this
Protected Sub dsDetail_PerformSelect(ByVal sender As Object, ByVal e As SD.LLBLGen.Pro.ORMSupportClasses.PerformSelectEventArgs2) Handles dsDetail.PerformSelect
Dim prefetchPath As New PrefetchPath2(DirectCast(EntityType.ProductEntity, Integer))
prefetchPath.Add(ProductEntity.PrefetchPathCategories)
prefetchPath.Add(ProductEntity.PrefetchPathSuppliers)
Using da As New DataAccessAdapter
da.FetchEntityCollection(e.ContainedCollection, e.Filter, 0, e.Sorter, prefetchPath)
End Using
End Sub
Protected Sub dsDetail_PerformWork(ByVal sender As Object, ByVal e As SD.LLBLGen.Pro.ORMSupportClasses.PerformWorkEventArgs2) Handles dsDetail.PerformWork
Dim data As UnitOfWork2 = e.Uow
Using da As New DataAccessAdapter
data.Commit(da, True)
End Using
'refresh the datasource for the grid to show the updated/inserted row
dsGrid.Refetch = True
End Sub
I still need to be able to do some validation/set field values for the product entity that is being updated/inserted and to retrieve the identity value for the inserted entities. How can I get at that entity in the PerformWork event?
Joined: 23-Jan-2005
I'm making some progress here so let me get you an update and then ask for information with a few specific items.
I am using the Northwind database and the Products table as my test case because it has all of the major data types plus some foreign keys, etc.
Here is what I am attempting to accomplish:
1) Use the LLBLGenDataSource controls to filter/view/edit/insert on a single page with three controls. A dropdownlist for the filtering, a gridview for summary information and a formview for detail view/edit/insert. 2) I was not looking for a code-free solution but a minimal code solution. I already have applications that are using LLBLGen in an ASP.NET 1.1 fashion (i.e. grid.DataSource = productCollection and txtProductName.Text = product.ProductName). The two-way binding is the main focus. 3) The formview should show "friendly" data rather than foreign key values. Using Northwind Products as an example, I want to see "Beverages" (CategoryName) not "1" (CategoryId). 4) I want to be able to control the update/insert data during the insert/update for validation purposes or just simplifying things. Two examples here. First, I'll hide the Discontinued field in the InsertTemplate and I'd like to set that value to 0 in the code. Second, I'll hide the LastUpdate field for both InsertTemplate and EditTemplate and I'd like to set that value to DateTime.Now. (I realize that having default field values in the database could handle much of this but let's assume that I can't do that for whatever reason). 5) After the insert/update, the grid should reflect the current information. For inserts, the selected row in the grid should be the inserted row.
As I stated in my other thread to Frans, I realize that some of these tasks are just ASP.NET and have nothing to do with LLBLGen or the LLBLGenDataSource controls.
Walaa, your suggestion of using the Prefetch paths was helpful to solve goal #3 above. However, it took me a while to understand where in the code I could add the Prefetch Path. Also, I found the UnitOfWork GetXX class members in the reference manual prior to your post and am using them but would like to see a best practice example of working with entities in the UnitOfWork.
Current questions (in priority order):
1) At one point, the dropdown list "All categories" (non) filter was working. Now it isn't and I can't figure out why. I was using code-behind specifically so I could allow an "All" choice. 2) Is there a better way to work with the entity(s) in a UnitOfWork? I'm just hardcoding to the first element but I don't think that's flexible or correct. 3) This is a 50/50 ASP.NET LLBLGen question. After doing an insert, I'd like to refresh the grid and then select the new row in the grid. It seems as though the row index behavior is different for a gridview when I'm using LLBLGenDataSource than it is when I'm doing 1.1 style databinding. I couldn't figure out a work-around for this for the inserts, I did manage a workaround for the row selection from the gridView. 4) With the MS datasource controls, I can specify an output parameter for an identity field and retrieve the value in the event handler. I see that I can add the output parameter and SQL Server is returning the information but there doesn't appear to be any way to get the parameter. I'm getting it via the UnitOfWork2.GetInsertQueue method but it seems like there should be a more direct way of getting to it.
Here is the web page code
<%@ Page Language="VB" MasterPageFile="~/templates/default.master" AutoEventWireup="false" CodeFile="editgrid.aspx.vb" Inherits="editgrid" title="Edit Grid" %>
<%@ MasterType TypeName="templates_default" %>
<asp:Content ID="Sub1" ContentPlaceHolderID="main" Runat="Server">
<asp:DropDownList ID="ddlCategoryFilter" runat="server"
AppendDataBoundItems="True" DataSourceID="dsCategory"
DataTextField="CategoryName" DataValueField="CategoryId" AutoPostBack="True">
<asp:ListItem Value="-1">--All Categories--</asp:ListItem>
</asp:DropDownList>
<asp:GridView ID="gridItems" runat="server" AllowPaging="True" AutoGenerateColumns="False"
CellPadding="4" DataKeyNames="ProductId" DataSourceID="dsGrid"
ShowFooter ="true"
ForeColor="#333333"
GridLines="None">
<FooterStyle CssClass="gridFooter" />
<RowStyle CssClass="gridItem" />
<EditRowStyle BackColor="#999999" />
<SelectedRowStyle CssClass="gridItemSelected" />
<PagerStyle BackColor="White" CssClass="gridPager" Font-Size="9pt" HorizontalAlign="Right" />
<HeaderStyle CssClass="gridHeader" />
<AlternatingRowStyle CssClass="gridItemAlternate" />
<PagerSettings Position="TopAndBottom" />
<Columns>
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:linkButton ID="btnEditRow" runat="server" CausesValidation="False"
CommandName="EditRow" CommandArgument='<%# Container.DataItemIndex %>'
Text="Edit" />
</ItemTemplate>
<FooterTemplate>
<asp:linkButton ID="btnAddRow" runat="server" CausesValidation="False"
CommandName="AddRow" CommandArgument="-1"
Text="Add" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Linkbutton ID="btnView" runat="server" CausesValidation="False"
CommandName="ViewRow" CommandArgument='<%# Container.DataItemIndex %>'
Text="View" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ProductId" HeaderText="ProductId" ReadOnly="True" SortExpression="ProductId" />
<asp:TemplateField HeaderText="Product Name">
<ItemTemplate>
<asp:HyperLink ID="lnkView" runat="server"
Text='<%# Eval("ProductName") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CategoryName" HeaderText="Category" SortExpression="CategoryId" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" DataFormatString="{0:c}" HtmlEncode="false"/>
<asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" />
<asp:BoundField DataField="LastUpdate" HeaderText="LastUpdate" SortExpression="LastUpdate" DataFormatString="{0:MMM-dd-yy}" HtmlEncode="false"/>
</Columns>
</asp:GridView>
<asp:Panel ID="pnlDetail" runat="server">
<asp:FormView ID="formData" runat="server"
DataKeyNames="ProductId" DataSourceID="dsDetail" >
<EditItemTemplate>
<table width="500px" >
<tr>
<td align="right" class="dataLabel" style="width: 150px">
Product Id</td>
<td align="left" class="dataCell">
<asp:Label ID="ProductIdLabel1" runat="server" Text='<%# Eval("ProductId") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Product Name</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ProductNameTextBox" runat="server" Text='<%# Bind("ProductName") %>' Columns="40">
</asp:TextBox><asp:RequiredFieldValidator ID="vreqProductName" runat="server" ControlToValidate="ProductNameTextBox"
ErrorMessage="Required" Display="Dynamic" ></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Supplier</td>
<td align="left" class="dataCell">
<asp:DropDownList ID="ddlSupplierID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsSupplier"
DataTextField="CompanyName"
DataValueField="SupplierId"
SelectedValue='<%# Bind("SupplierID") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="vreqSupplier" runat="server" ControlToValidate="ddlSupplierID"
ErrorMessage="Required" InitialValue="-1" Display="Dynamic" ></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Category
</td>
<td align="left" class="dataCell">
<asp:DropDownList ID="ddlCategoryID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsCategory"
DataTextField="CategoryName"
DataValueField="CategoryID"
SelectedValue='<%# Bind("CategoryId") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="vreqCategoryID" runat="server" ControlToValidate="ddlCategoryID"
Display="Dynamic" ErrorMessage="Required" InitialValue="-1"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Quantity Per Unit</td>
<td align="left" class="dataCell">
<asp:TextBox ID="QuantityPerUnitTextBox" runat="server" Text='<%# Bind("QuantityPerUnit") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqQuantityPerUnit" runat="server" ControlToValidate="QuantityPerUnitTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Unit Price</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitPriceTextBox" runat="server" Text='<%# Bind("UnitPrice") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitPrice" runat="server" ControlToValidate="UnitPriceTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitPrice" runat="server" ControlToValidate="UnitPriceTextBox"
Display="Dynamic" ErrorMessage="Must be > 0" Operator="GreaterThan" Type="Double"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units In Stock
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsInStockTextBox" runat="server" Text='<%# Bind("UnitsInStock") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitsInStock" runat="server" ControlToValidate="UnitsInStockTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitsInStock" runat="server" ControlToValidate="UnitsInStockTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units On Order
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsOnOrderTextBox" runat="server" Text='<%# Bind("UnitsOnOrder") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitsOnOrder" runat="server" ControlToValidate="UnitsOnOrderTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitsOnOrder" runat="server" ControlToValidate="UnitsOnOrderTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Reorder Level</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ReorderLevelTextBox" runat="server" Text='<%# Bind("ReorderLevel") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqReorderLevel" runat="server" ControlToValidate="ReorderLevelTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomReorderLevel" runat="server" ControlToValidate="ReorderLevelTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Discontinued</td>
<td align="left" class="dataCell">
<asp:CheckBox ID="DiscontinuedCheckBox" runat="server" Checked='<%# Bind("Discontinued") %>' /></td>
</tr>
<tr>
<td align="right" class="dataLabel">
</td>
<td align="left" class="dataCell">
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
Text="Update" >
</asp:LinkButton>
<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel"
Text="Cancel">
</asp:LinkButton></td>
</tr>
</table>
</EditItemTemplate>
<InsertItemTemplate>
<table width="500px" >
<tr>
<td align="right" class="dataLabel" >
Product Name</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ProductNameTextBox" runat="server" Text='<%# Bind("ProductName") %>' Columns="40">
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqProductName" runat="server" ErrorMessage="Required"
ControlToValidate ="ProductNameTextBox"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Supplier</td>
<td align="left" class="dataCell">
<asp:DropDownList ID="ddlSupplierID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsSupplier"
DataTextField="CompanyName"
DataValueField="SupplierId"
SelectedValue='<%# Bind("SupplierId") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="vreqSupplier" runat="server"
ErrorMessage="Required" ControlToValidate="ddlSupplierID" InitialValue="-1"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Category
</td>
<td align="left" class="dataCell" style="height: 24px">
<asp:DropDownList ID="ddlCategoryID" runat="server"
AppendDataBoundItems="true"
DataSourceID="dsCategory"
DataTextField="CategoryName"
DataValueField="CategoryID"
SelectedValue='<%# Bind("CategoryId") %>' >
<asp:ListItem Value="-1">--Select One--</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Quantity Per Unit</td>
<td align="left" class="dataCell">
<asp:TextBox ID="QuantityPerUnitTextBox" runat="server" Text='<%# Bind("QuantityPerUnit") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqQuantityPerUnit" runat="server" ControlToValidate="QuantityPerUnitTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Unit Price</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitPriceTextBox" runat="server" Text='<%# Bind("UnitPrice") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitPrice" runat="server" ControlToValidate="UnitPriceTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitPrice" runat="server" ControlToValidate="UnitPriceTextBox"
Display="Dynamic" ErrorMessage="Must be > 0" Operator="GreaterThan" Type="Double"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units In Stock
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsInStockTextBox" runat="server" Text='<%# Bind("UnitsInStock") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitsInStock" runat="server" ControlToValidate="UnitsInStockTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitsInStock" runat="server" ControlToValidate="UnitsInStockTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units On Order
</td>
<td align="left" class="dataCell">
<asp:TextBox ID="UnitsOnOrderTextBox" runat="server" Text='<%# Bind("UnitsOnOrder") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqUnitsOnOrder" runat="server" ControlToValidate="UnitsOnOrderTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomUnitsOnOrder" runat="server" ControlToValidate="UnitsOnOrderTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Reorder Level</td>
<td align="left" class="dataCell">
<asp:TextBox ID="ReorderLevelTextBox" runat="server" Text='<%# Bind("ReorderLevel") %>'>
</asp:TextBox>
<asp:RequiredFieldValidator ID="vreqReorderLevel" runat="server" ControlToValidate="ReorderLevelTextBox"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
<asp:CompareValidator ID="vcomReorderLevel" runat="server" ControlToValidate="ReorderLevelTextBox"
Display="Dynamic" ErrorMessage="Must be >= 0" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0"></asp:CompareValidator></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
</td>
<td align="left" class="dataCell">
<asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert"
Text="Insert">
</asp:LinkButton>
<asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel"
Text="Cancel">
</asp:LinkButton>
</td>
</tr>
</table>
</InsertItemTemplate>
<ItemTemplate>
<table width="500px" >
<tr>
<td align="right" class="dataLabel" style="width: 150px">
Product Id</td>
<td align="left" class="dataCell" >
<asp:Label ID="ProductIdLabel" runat="server" Text='<%# Eval("ProductId") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Product Name
</td>
<td align="left" class="dataCell" >
<asp:Label ID="ProductNameLabel" runat="server" Text='<%# Bind("ProductName") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Quantity Per Unit
</td>
<td align="left" class="dataCell" >
<asp:Label ID="QuantityPerUnitLabel" runat="server" Text='<%# Bind("QuantityPerUnit") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Unit Price</td>
<td align="left" class="dataCell" >
<asp:Label ID="UnitPriceLabel" runat="server" Text='<%# Bind("UnitPrice") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Units In Stock</td>
<td align="left" class="dataCell" >
<asp:Label ID="UnitsInStockLabel" runat="server" Text='<%# Bind("UnitsInStock") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" style="height: 18px" >
Units On Order
</td>
<td align="left" class="dataCell" style="height: 18px" >
<asp:Label ID="UnitsOnOrderLabel" runat="server" Text='<%# Bind("UnitsOnOrder") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Reorder Level</td>
<td align="left" class="dataCell" >
<asp:Label ID="ReorderLevelLabel" runat="server" Text='<%# Bind("ReorderLevel") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Discontinued
</td>
<td align="left" class="dataCell" >
<asp:CheckBox ID="DiscontinuedCheckBox" runat="server" Checked='<%# Bind("Discontinued") %>'
Enabled="false" /></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
Last Update</td>
<td align="left" class="dataCell" >
<asp:Label ID="LastUpdateLabel" runat="server" Text='<%# Bind("LastUpdate") %>'></asp:Label></td>
</tr>
<tr>
<td align="right" class="dataLabel" >
</td>
<td align="left" class="dataCell" >
<br />
<asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit"
Text="Edit"></asp:LinkButton>
<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete"
Text="Delete" OnClientClick="javascript:return confirm('Are you sure you want to delete this item?');" />
<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New"
Text="New"></asp:LinkButton>
</td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>
</asp:Panel>
<cc1:LLBLGenProDataSource2 ID="dsGrid" runat="server"
AdapterTypeName="DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
DataContainerType="EntityCollection" EntityFactoryTypeName="DMS.Northwind.DAL.FactoryClasses.ProductEntityFactory, DMS.Northwind.DAL" LivePersistence="False" >
</cc1:LLBLGenProDataSource2>
<cc1:LLBLGenProDataSource2 ID="dsDetail" runat="server"
AdapterTypeName="DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
DataContainerType="EntityCollection" AllowDuplicates="False" EntityFactoryTypeName="DMS.Northwind.DAL.FactoryClasses.ProductEntityFactory, DMS.Northwind.DAL"
LivePersistence="False">
<SelectParameters>
<asp:ControlParameter ControlID="gridItems" Name="ProductId" PropertyName="SelectedValue"
Type="Int32" />
</SelectParameters>
</cc1:LLBLGenProDataSource2>
<cc1:LLBLGenProDataSource2 ID="dsSupplier" runat="server" AdapterTypeName="DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
DataContainerType="EntityCollection" EntityFactoryTypeName="DMS.Northwind.DAL.FactoryClasses.SupplierEntityFactory, DMS.Northwind.DAL">
</cc1:LLBLGenProDataSource2>
<cc1:LLBLGenProDataSource2 ID="dsCategory" runat="server" AdapterTypeName="DMS.Northwind.DAL.DbSpecific.DataAccessAdapter, DMS.Northwind.DAL.DbSpecific"
DataContainerType="EntityCollection" EntityFactoryTypeName="DMS.Northwind.DAL.FactoryClasses.CategoryEntityFactory, DMS.Northwind.DAL">
</cc1:LLBLGenProDataSource2>
</asp:Content>
Code File:
Partial Class editgrid
Inherits System.Web.UI.Page
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
#Region "Dropdown filter events"
Protected Sub ddlCategoryFilter_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlCategoryFilter.SelectedIndexChanged
Trace.Warn("ddlCategoryFilter_SelectedIndexChanged")
gridItems.SelectedIndex = -1
gridItems.PageIndex = 0
If Me.ddlCategoryFilter.SelectedValue = "-1" Then
Me.dsGrid.SelectParameters.Clear()
Else
setGridFilter()
End If
End Sub
#End Region
#Region "GridView events"
Protected Sub gridItems_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles gridItems.DataBound
Trace.Warn("gridItems_DataBound")
End Sub
Protected Sub gridItems_PageIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles gridItems.PageIndexChanged
'reset the grid selected index
gridItems.SelectedIndex = -1
formData.Visible = False
End Sub
Protected Sub gridItems_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gridItems.RowCommand
Dim grid As GridView = Me.gridItems
Dim idx As Integer = Convert.ToInt32(e.CommandArgument)
Dim keyName As String = "ProductId"
Dim key As String
Dim rowIndex As Integer
Trace.Warn(e.CommandName & " Command argument: " & e.CommandArgument)
If e.CommandName.ToLower = "page" Then
'pager commands, nothing to do with these here yet
'but they can cause errors with the next section
Exit Sub
End If
''pager work-around to get the actual datasource row index
If idx >= 0 Then
If grid.PageIndex = 0 Then
rowIndex = idx
Else
'this is the normal formula for standard databinding
rowIndex = idx - (grid.PageIndex * grid.PageSize)
' this is the additional formula for LLBLGenDatasource control
If rowIndex < 0 Then
rowIndex = idx + (grid.PageIndex * grid.PageSize)
End If
End If
'use this to get any datakey values, names are case-sensitive
key = gridItems.DataKeys(rowIndex).Values(keyName)
Else
key = "0"
End If
Select Case e.CommandName.ToLower
Case "select"
'not using this at the moment
Case "viewrow"
formData.ChangeMode(FormViewMode.ReadOnly)
Case "editrow"
formData.ChangeMode(FormViewMode.Edit)
Case "addrow"
formData.ChangeMode(FormViewMode.Insert)
End Select
formData.Visible = True
'don't know if this works correctly in all situations yet
gridItems.SelectedIndex = rowIndex
End Sub
#End Region
#Region "FormView events"
Protected Sub formData_ItemDeleted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewDeletedEventArgs) Handles formData.ItemDeleted
gridItems.SelectedIndex = -1
formData.Visible = False
End Sub
#End Region
#Region "Grid Datasource control events"
Protected Sub dsGrid_PerformSelect(ByVal sender As Object, ByVal e As SD.LLBLGen.Pro.ORMSupportClasses.PerformSelectEventArgs2) Handles dsGrid.PerformSelect
Dim prefetchPath As New PrefetchPath2(DirectCast(EntityType.ProductEntity, Integer))
prefetchPath.Add(ProductEntity.PrefetchPathCategories)
prefetchPath.Add(ProductEntity.PrefetchPathSuppliers)
Using da As New DataAccessAdapter
da.FetchEntityCollection(e.ContainedCollection, e.Filter, 0, e.Sorter, prefetchPath)
End Using
End Sub
#End Region
#Region "Formview Datasource control events"
Protected Sub dsDetail_PerformSelect(ByVal sender As Object, ByVal e As SD.LLBLGen.Pro.ORMSupportClasses.PerformSelectEventArgs2) Handles dsDetail.PerformSelect
Dim prefetchPath As New PrefetchPath2(DirectCast(EntityType.ProductEntity, Integer))
prefetchPath.Add(ProductEntity.PrefetchPathCategories)
prefetchPath.Add(ProductEntity.PrefetchPathSuppliers)
Using da As New DataAccessAdapter
da.FetchEntityCollection(e.ContainedCollection, e.Filter, 0, e.Sorter, prefetchPath)
End Using
End Sub
Protected Sub dsDetail_PerformWork(ByVal sender As Object, ByVal e As SD.LLBLGen.Pro.ORMSupportClasses.PerformWorkEventArgs2) Handles dsDetail.PerformWork
Dim data As UnitOfWork2 = e.Uow
Dim product As ProductEntity
Select Case formData.CurrentMode
Case FormViewMode.Edit
data.GetEntityElementsToUpdate.Item(0).Entity.Fields.Item("LastUpdate").CurrentValue = DateTime.Now
Case FormViewMode.Insert
data.GetEntityElementsToInsert.Item(0).Entity.Fields.Item("LastUpdate").CurrentValue = DateTime.Now
data.GetEntityElementsToInsert.Item(0).Entity.Fields.Item("Discontinued").CurrentValue = False
'can get an entity reference like this
'product = data.GetEntityElementsToInsert.Item(0).Entity
'With product
' .LastUpdate = DateTime.Now
' .Discontinued = False
'End With
'dont really understand how to select and remove
' an entity from the collection without using the item index
End Select
'save the data, VS2005 syntax
Using da As New DataAccessAdapter
data.Commit(da, True)
End Using
dsGrid.Refetch = True
If formData.CurrentMode = FormViewMode.Insert Then
product = data.GetInsertQueue.Item(0).Entity
'not working yet
selectGridRowByKey(product.ProductId.ToString, "ProductId")
formData.Visible = True
End If
End Sub
#End Region
#Region "Helper methods"
Sub setGridFilter()
Dim id As Integer = Convert.ToInt32(Me.ddlCategoryFilter.SelectedValue)
dsGrid.FilterToUse = _
New RelationPredicateBucket(ProductFields.CategoryId = id)
dsGrid.Refetch = True
End Sub
Sub selectGridRowByKey(ByVal key As String, ByVal keyName As String)
'Not functional yet
Dim grid As GridView = Me.gridItems
Dim isFound As Boolean
Dim rowIndex As Integer
Dim pageNumber As Integer
Try
'For Each row As GridViewRow In grid.Rows?
For i As Integer = 0 To grid.Rows.Count
Trace.Warn("Grid Index: " & i.ToString & ", count is " & grid.Rows.Count.ToString)
If key = grid.DataKeys(i).Values(keyName).ToString Then
'get the correct page
If i > grid.PageSize Then
pageNumber = (i \ grid.PageSize) - 1
End If
grid.PageIndex = pageNumber
grid.SelectedIndex = i
isFound = True
Exit For
End If
Next
Catch ex As Exception
Trace.Warn(ex.ToString)
End Try
If Not isFound Then
grid.SelectedIndex = -1
grid.PageIndex = 0
End If
End Sub
#End Region
End Class
Oh yeah, this page is approx 250 lines of code, including blank lines and comments. The same functionality with ASP.NET 1.1 style data binding is over 750 lines. I call that a definite win but it still feels like it's been more painful to get here than it should be.
jovball wrote:
Walaa, your suggestion of using the Prefetch paths was helpful to solve goal #3 above. However, it took me a while to understand where in the code I could add the Prefetch Path.
In the last part of my advanced asp.net 2.0 with llblgen pro article, this is illustrated, but you might have overlooked it
Current questions (in priority order): 1) At one point, the dropdown list "All categories" (non) filter was working. Now it isn't and I can't figure out why. I was using code-behind specifically so I could allow an "All" choice.
you specify as value '-1'. You don't have an event handler set in the dropdownlist, and as far as I can see, you don't wire the events yourself. In ASP.NET 2.0, events aren't wired anymore in the code behind, they're autowired with the declarative specified eventhandler method in the control HTML. Perhaps that's it?
2) Is there a better way to work with the entity(s) in a UnitOfWork? I'm just hardcoding to the first element but I don't think that's flexible or correct.
The grids etc. always execute on a single row, because they post-back at every action. So there's always just 1 entity in the UoW. If you're using a grid like ASPxGrid by DevExpress, which is an Ajax grid, you'll see multiple entities in the UoW, as it collects all work and then passes it all to the datasourcecontrol when the user clicks save.
3) This is a 50/50 ASP.NET LLBLGen question. After doing an insert, I'd like to refresh the grid and then select the new row in the grid. It seems as though the row index behavior is different for a gridview when I'm using LLBLGenDataSource than it is when I'm doing 1.1 style databinding. I couldn't figure out a work-around for this for the inserts, I did manage a workaround for the row selection from the gridView.
A fetch is done after the insert, as the grid will simply call ExecuteSelect on the datasourcecontrol. So where the row ends up depends on the sorting set.
This is one of those stupid things with ASP.NET: a lot of things are going on behind the scenes but no-one knows when what happens.
4) With the MS datasource controls, I can specify an output parameter for an identity field and retrieve the value in the event handler. I see that I can add the output parameter and SQL Server is returning the information but there doesn't appear to be any way to get the parameter. I'm getting it via the UnitOfWork2.GetInsertQueue method but it seems like there should be a more direct way of getting to it.
To display the ID or something? if you need that, you indeed should use the PerformWork event and obtain the ID there.