.NET 4.5 Gridview with DropDownList in EditItemTemplate UpdateMethod - asp.net

I have Gridview with list of ManufacturerTypes that is related with Manufacturers... So each ManufacturerType has a Manufacturer (2 tables -> 2 entities). When I want to update item ManufacturerType I wan`t to be possible to update Title from Entity ManufacturerType but also change the (Manufacturer) relation if the dropdownlist selectedvalue change.
<asp:GridView ID="gvManufacturerTypes" runat="server" DataKeyNames="manufacturerTypeId"
AutoGenerateColumns="false" GridLines="Vertical" CssClass="gridview"
CellPadding="4" ItemType="Entities.Models.ManufacturerType" SelectMethod="GetManufacturerTypesWithParams"
UpdateMethod="UpdateItem" DeleteMethod="DeleteItem"
AllowPaging="true" AllowSorting="true" PageSize="20" PagerSettings-FirstPageText="Prvi"
PagerSettings-LastPageText="Zadnji" PagerSettings-Mode="NumericFirstLast"
OnCallingDataMethods="gvManufacturerTypes_CallingDataMethods">
<Columns>
<asp:TemplateField HeaderText="Proizvajalec">
<ItemTemplate>
<asp:Label ID="lblManufacturer" Text='<%# Item.Manufacturer.Title %>' runat="server" />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlManufacturers" runat="server" ItemType="Entities.Models.Manufacturer" SelectMethod="GetManufacturers" SelectedValue='<%# Item.Manufacturer.ManufacturerId %>'
DataTextField="Title" DataValueField="manufacturerId" OnCallingDataMethods="ddlManufacturers_CallingDataMethods">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
<asp:DynamicField DataField="Title" />
<asp:CommandField ShowEditButton="true" EditText="Uredi" UpdateText="Shrani" CancelText="Prekliči" ItemStyle-Width="80" />
<asp:CommandField ShowDeleteButton="true" DeleteText="Izbriši" ItemStyle-Width="80" />
</Columns>
<PagerStyle CssClass="gridview_pager" />
</asp:GridView>
It generates me UpdateItem method and I change the load item and save changes sections like below:
// The id parameter name should match the DataKeyNames value set on the control
public void UpdateItem(int manufacturerTypeId, ModelMethodContext context)
{
ManufacturerType item = null;
// Load the item here
item = _manufacturerTypeRepository.GetAllWithRelations(m => m.Manufacturer)
.Where(x => x.ManufacturerTypeId == manufacturerTypeId).SingleOrDefault();
if (item == null)
{
// The item wasn't found
context.ModelState.AddModelError("", String.Format("Proizvajalec z idjem {0} ne obstaja.", manufacturerTypeId));
return;
}
context.TryUpdateModel(item);
if (context.ModelState.IsValid)
{
// Save changes here
_manufacturerTypeRepository.Save();
}
}
I also call the Include where I get the ManufacturerType entity with Include("Manufacturer") ... so I get the current ManufacturerType, and the TryUpdateModel method also change the Title of ManufacturerType (if I change it on edit in gridview), but Manufacturer always stays the same... I have also try to put the dropdownlist as control-parameter to UpdateMethod like
public void UpdateItem(int manufacturerTypeId, [Control] manufacturerId, ModelMethodContext context)
but it is always null... So I don`t know how to transfare value from dropdownlist to UpdateItem method (UpdateItem is not in codebehind of ManufacturerTypes.aspx but it is in busines logic layer) ManufacturerTypeBL.cs...
I didn`t find any solution for this that will use new features like ItemType in gridview and Select method and SelectMethod in dropdownlist etc...
Maybe I need to change the UpdateItem method with old fasioned way OnUpdating method and read the values from dropdown and lather call the busines logic layer with params?
EDIT - > add model classes (Manufacturer, ManufacturerType)
public class Manufacturer
{
[Key, ForeignKey("ManufacturerType")]
public int ManufacturerId { get; set; }
[StringLength(255)]
public string Title { get; set; }
public ManufacturerType ManufacturerType { get; set; }
}
public class ManufacturerType
{
[Key]
public int ManufacturerTypeId { get; set; }
[StringLength(50)]
public string Title { get; set; }
public Manufacturer Manufacturer { get; set; }
}

From what I can understand,
In the EditItemTempalte set SelectedValue='<%# Bind("ManufacturerId")%>'. i.e. Property name for the ManufacturerId in ManufacturerType Entity.
Also, it should not be required to fetch the relation (in the select query). If you fetch ManufacturerType item, and use correct property name in the EditTemplate controls, it should work fine.
If you can post your Model classes (Manufacturer and ManufacturerType) it will be more helpful to understand the issue.

Related

Make a form field selection values dependent on another field value

I am editing the AP301000 screen, Bills and Adjustments, in a customization project.
I added two new fields to the form, which are both in the APRegisterExt class.
1. PONbr
2. ReceiptNbr
When a user selects a PO number, I want the ReceiptNbr selection values to be restricted to only the receipt records which have the same PO number.
I tried using a PXSelector attribute on ReceiptNbr, but because the PONumber is in an extension class, I cannot use Current<> to access this field.
Any ideas?
On your second CustomField's Selector attribute definition use Current<> statement for filtering, see below:
#region UsrCustomField1
[PXDBInt]
[PXUIField(DisplayName="CustomField1")]
[PXSelector(typeof(Search<DAC.Field>),
typeof(DAC.Field),
typeof(DAC.Field),
SubstituteKey= typeof(DAC.Field))]
public virtual int? UsrCustomField1 { get; set; }
public abstract class usrCustomField1 : IBqlField { }
#endregion
#region UsrCustomField2Dependent
[PXDBInt]
[PXUIField(DisplayName="CustomField2Dependent")]
[PXSelector(typeof(Search<DAC.Field, Where<DAC.Field, Equal<Current<UsrCustomField1>>>>),
typeof(DAC.Field),
typeof(DAC.Field),
SubstituteKey= typeof(DAC.Field))]
public virtual int? UsrCustomField2Dependent { get; set; }
public abstract class usrCustomField2Dependent : IBqlField { }
#endregion
Then on your ASPX file make sure you have added CommitChanges=True and AutoRefresh=true properties, see below:
<px:PXSelector runat="server" ID="CstPXSelector2" DataField="UsrCustomField1" CommitChanges="True" AutoRefresh="True" />
<px:PXSelector runat="server" ID="CstPXSelector1" DataField="UsrCustomField2Dependent" CommitChanges="True" AutoRefresh="True" />

ASP.Net ObjectDataSource Data Binding

I have two classes:
public class Contact{
public string contact { get; set; }
public string contact_type { get; set; }
}
public class Person{
public string first_name { get; set; }
public string last_name { get; set; }
Contact phone
}
In my asp.net application I need to see list of persons in a gridview.
I use ObjectDataSource to bind List. But only two columns: first_name and last_name are presents in the gridview. It is important to see contact of person.
In other words, how to bind subclass Contact to the same gridview.
What is the best way to do this? I don't like idea to use DataTable.
Thanks!
I think your best bet is to use template field and eval to access inner object fields:
<asp:TemplateField HeaderText="Contact">
<ItemTemplate>
<%# Eval("phone.contact") %>
</ItemTemplate>
</asp:TemplateField>
If you are using auto generated columns feature, keep it, declared columns will be appended after generated ones.

Custom Control Event not firing inside a user control

I implement a custom control that handle post back event:
namespace CalendarControls
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class CalendarPostback : WebControl, IPostBackEventHandler
{
public delegate void CalendarPostBackHandler(object sender, CalendarPostbackEventArgs e);
public event CalendarPostBackHandler CalendarPostBack;
public CalendarPostback()
{
}
#region IPostBackEventHandler Members
public void RaisePostBackEvent(string eventArgument)
{
string[] values = eventArgument.Split('|');
CalendarPostbackEventArgs args = new CalendarPostbackEventArgs();
args.EventType = (eEventType)Convert.ToInt32(values[0]);
if (args.EventType == eEventType.Insert)
args.EventDate = Convert.ToDateTime(values[1]);
else
args.EventId = Convert.ToInt32(values[1]);
if (CalendarPostBack != null)
CalendarPostBack(this, args);
}
#endregion
}
public class CalendarPostbackEventArgs : EventArgs
{
public CalendarPostbackEventArgs()
{
}
public eEventType EventType
{
get;
set;
}
public DateTime EventDate
{
get;
set;
}
public int? EventId
{
get;
set;
}
}
}
and I use this custom control in a usercontrol ,and call it on a button click inside my usercontrol with following javascript code:
function CallPostBack(eventArguments) {
__doPostBack('<%=ctl1.ClientID %>', eventArguments);
}
and my html code in usercontrol:
<input type="button" value="Insert" onclick="CallPostBack('1|2014/06/12')" />
<CalendarControls:CalendarPostback ID="ctl1" runat="server" ClientIDMode="Static" OnCalendarPostBack="ctl1_CalendarPostBack" />
but when I click on my button, page postback occur but ctl1_CalendarPostBack event not fired. also I must to say that I add user control directly to aspx page (not dynamically) and my aspx page have a master page.
now I have two question:
what's wrong with my code? how to solve this issue?
if I want to add my custom control to an update panel and I want to have an async post back, what I must do?
thank you,
best regards
I found problem! when we use master page ,client id and unique id of control is different and we must to use unique id instead of client id:
function CallPostBack(eventArguments) {
__doPostBack('<%=ctl1.UniqueID %>', eventArguments);
}

Error: "A field or property with the name was not found on the selected data source" get only on server

I publish my project without any warning on local iis and it works correctly (localhost/[myprojectName]). so, i upload them to server with cute ftp. but in server i get this error apear for all my filed like [tableName].[filedName]:
A field or property with the name 'ConfirmStatuse.Name' was not found
on the selected data source
here's my code:
<asp:GridView ID="ordergv" runat="server" DataKeyNames="Id" AutoGenerateColumns="False" DataSourceID="SummaryOfOrderSrc" AllowSorting="True">
<Columns>
<asp:CommandField SelectText="select" ShowSelectButton="True" ButtonType="Button"/>
<asp:BoundField DataField="OrderId" />
<asp:BoundField DataField="ConfirmStatuse.Name" />
<asp:BoundField DataField="OrderStatuse.Name"/>
<asp:BoundField DataField="PaymentStatuse.Name"/>
<asp:BoundField DataField="ShipmentStatuse.Name" />
<asp:TemplateField >
<ItemTemplate>
<asp:Label ID="CreatedDateLabel" runat="server" Text='<%# GetPersianDate( Eval("CreatedDate")) %>' /></ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:LinqDataSource ID="SummaryOfOrderSrc" runat="server" ContextTypeName="Ahooratech.DAL.DataClasses1DataContext" EntityTypeName="" OrderBy="CreatedDate desc" TableName="Orders">
</asp:LinqDataSource>
I check the size of my project in local iis and on server. both of them are same(8,459,009 bytes)
so it means i use same database and same files for run my application for run on local and server. so why i get this error only in server?
The only difference here is on version of iis, i think my server iis version is 7.0. but is it important for i get this error?!!! i don't think so. i'm really confused.
(My local project and server project use same connection string).
EDIT: I publish project on another host and it works! but it doesn't work on my original server yet.
This is the same issue to the one described here - Binding to Navigation Property causes " A field or property with the name 'X.X' was not found on the selected data source" in IIS 6 ONLY
It appears to be an issue with the BoundField control element. As suggested in an answer provided by user Anant in the article linked above, you can convert the BoundField to a TemplateField and it will work (using "OrderStatuse.Name" in your example). That solution worked for me.
Although this really doesn't explain why IIS6 can't support the BoundField in this way.
Mind boggling.
I found the IIS Version on my server is 6. but my local is 7.5.
I publish my project on another server with iis 7.5 and it works
Solution1: I create a summaryOfOrder like this:
class summaryOfOrder
{
public int Id { get; set; }
public int OrderId { get; set; }
public string ConfirmStatusName { get; set; }
public string OrderStatusName { get; set; }
public string PaymentStatusName { get; set; }
public string ShippingStatusName { get; set; }
public string CreatedDate { get; set; }
}
and change
<asp:BoundField DataField="ConfirmStatuse.Name" />
to
<asp:BoundField DataField="ConfirmStatusName" />
and bind class to grid by
gv.datasource = mySummryOfOrder;
gv.databind();
and initialize a list of this type and bind it to grid programmatically
Update solution 2 convert
asp:BoundField
to
asp:TemplateField
and using
<%# Eval("Worker.FullName")%>
I have sorted out with adding those bound fields in the selected query.
Error message:
A field or property with the name 'tax_percentage' was not found on the selected data source
Solution:
I didn't select the tax_percentage in the select query so the above error message came. Just select the tax_percentage in my query.
If your datasource is a list of objects, certify that the properties of your class are definied as public, like this:
class YourClass
{
public int Id { get; set; }
public string Name{ get; set; }
}
opposite to:
class YourClass
{
private int Id { get; set; }
private string Name{ get; set; }
}
Regards

ASP.NET Custom control, is it possible to restrict contents of a template?

Some ASP.NET controls only permit items of certain types, for example:
<uc:MyControl runat="server"....>
<MyTableTemplate>
<MyTableRow .... />
<MyTableRow .... />
<MyTableRow .... />
</MyTableTemplate>
</uc:MyControl>
I'm trying to recreate this in my own custom control, such that you can only put MyTableRow objects into the template and Visual Studio will prevent the designer putting anything else in.
I've been looking at the ControlBuilder class but I am not fully certain it does what I want. In addition the examples do not mention the nesting I have above where the array of MyTableRow is within another template field.
Does anyone know how to achieve this?
Edit: The UpdatePanel seems to work this way: If you declare an UpdatePanel like this:
<asp:UpdatePanel>
<Triggers>
</Triggers>
</asp:UpdatePanel>
You cannot put anything in the Triggers section other than the two specific controls listed in intellisense, and you get a design-time error if you try. This is the exact behaviour I wish to mimic.
====
I tried to implement Alex's suggestion, here is my code:
public partial class MyControl : System.Web.UI.UserControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public ActionButtonCollection ActionButtons
{
get;
set;
}
}
public class ActionButtonCollection : Collection<ActionButton>
{
}
public abstract class ActionButtonBase
{
public string Test { get; set; }
}
public class ActionButton : ActionButtonBase
{
}
However with this code there is no intellisense inside
<uc:MyCustomControl runat="server">
<ActionButtons>
</ActionButtons>
</uc:MyCustomControl >
EDIT: added a link to the example of doing this to google docs.
Firstly, build the website and then you'll be able use this control with IntelliSense.
Actually, <Triggers> property of UpdatePanel is not a template. It is just a collection of objects. You could achieve this by declaring you own class and a class which inherit Collection<YourClass>; then just add the public property of Collection<YourClass> type to your control and you will be able to archive the "update panel triggers" behaviour.
Here is an example:
public abstract class UpdatePanelTrigger
{
public string ControlId { get; set; }
}
public class UpdatePanelTrigger1 : UpdatePanelTrigger
{
}
public class UpdatePanelTrigger2 : UpdatePanelTrigger
{
}
public class UpdatePanelTriggerCollection : Collection<UpdatePanelTrigger>
{
}
and finally, your control:
public class MyControl : WebControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public UpdatePanelTriggerCollection Triggers { get; set; }
}
then you could use it on your page:
<my:MyControl runat="Server">
<Triggers>
<my:UpdatePanelTrigger1 ControlId="ctrl1" />
<my:UpdatePanelTrigger2 ControlId="ctrl2" />
</Triggers>
</my:MyControl>
BTW, you cannot put anything to the Triggers section other than types which inherit from the UpdatePanelTrigger class.

Resources