Pass value from ObjectDataSource object level to ASP .NET Control - asp.net

I'm working with ObjectDataSource and FormView control.
In ObjectDataSource I have a type specified, and a method that performs Insert operation. However, once Insert is done, I would like to redirect the user to other page, and I need ID of newly created/persisted object.
So in FormView:
OnItemInserted="OnFormItemInserted"
handler I need to access that ID. But how to pass that id gracefully from ObjectDataSource level? I could use
HttpContext.Current.Items
inside ObjectDataSource handling object, but I don't like it, as my handling type do not know anything about ASP .NET (separation of concerns?).
Thanks

Have you tried something simple like this:
In your Data object
Update your insert method configured in the ObjectDataSource control to return the generated ID:
public int Insert(string firstName, int lastname)
{
// return the ID generated by the insert command
return 4;
}
ASPX code behind
And that's it, in your page where you are handling the Inserted event:
protected void ods_Inserted(object sender, ObjectDataSourceStatusEventArgs e)
{
var res = e.ReturnValue.ToString();
this.lblMessage.Text = res;
// add your cool additional logic and redirect stuff
}

Related

Initialize values in AX 2012 Wizard controls....

I have created a wizard in Ax 2012 using wizard>wizard and i am calling this wizard from Custtablelistpage form... now, i have put some controls in this wizard like CustAccount, and i need to initialize value in this control from selected record in Custtablelistpage form....
I am trying to perform this using Args class, but it is not working, please suggest some solutions..
please create one wizard in AX 2012 using tools>wizard>wizard
then, please put menu item of this wizard somewhere on custtablelistpage.
After that, please put one field named Customer account on welcome tab of wizard.
Now, if you any record that is displayed in custtablelistpage form, please select that.
My task is to display the Account num of selected record to my wizard when i am clicking the menu item button which i have put on custtablelistpage.
Actually, i have written some code,, which is is working absolutely fine for normal forms. but it is not working for Wizard and i am not getting value to initialize in my control on wizard.
Ok, I took some time to try this out and I have two possible solutions for you.
You can do it by using unbound controls and pass in the selected record
Or you could use a datasource on the wizard form and filter on the selected values
First let's try and do it by using a simple unbound control. Start by adding a CustTable member variable and parameter method to your wizard class.
public class MyTestWizardWizard extends SysWizard
{
CustTable mySelectedCustomer;
}
public CustTable parmMySelectedCustomer(CustTable _mySelectedCustomer = mySelectedCustomer)
{
;
mySelectedCustomer = _mySelectedCustomer;
return mySelectedCustomer;
}
Then in your form, you can overwrite the init method and do the following :
void init()
{
int controlid;
FormStringControl fsControl;
;
super();
if (element.Args().caller())
{
sysWizard = element.Args().caller();
// Get the control id of the CustomerId control
controlid = element.controlId(formControlStr(MyTestWizardWizard, CustomerId));
// Check if we actually have a form string control
if(element.control(controlid) is FormStringControl)
{
// Cast to the FormStringControl type
fsControl = element.control(controlid) as FormStringControl;
// Now fill in the field value
fsControl.text(sysWizard.parmMySelectedCustomer().AccountNum);
}
}
else
{
MyTestWizardWizard::main(new args());
element.closeCancel();
}
}
So what you actually do here is just fetch the selected record stored in you wizard class. Then we check if the control we want to assign values to is actually the right control to put the value in.
Though this is working, I would prefer a second method. That would be to use a datasource on the form and put a range on the selected record like this. Just put the CustTable as a datasource on the form and place your control as you would normally do.
Then, make sure the init method is performing the super() call at the bottom to make sure initialisation is done before calling the datasource methods:
void init()
{
;
// make sure the sysWizard is already initialized before the super to make sure the init on the datasource has an instance of sysWizard
if (element.Args().caller())
{
sysWizard = element.Args().caller();
}
else
{
MyTestWizardWizard::main(new args());
element.closeCancel();
}
super();
}
Then overwrite the init method on the datasource to put a range on the recId field of the custTable.
Please mind the you could assign the value of the range in the ExecuteQuery method, but for this case, I just do it here.
public void init()
{
;
super();
SysQuery::findOrCreateRange(this.query().dataSourceTable(tableNum(CustTable)), fieldNum(CustTable, RecId)).value(queryValue(SysWizard.parmMySelectedCustomer().RecId));
}
Now when your wizard is run, the args passes the record to your wizard class, the form picks it up on the init of the datasource and puts a range on the record that you have selected. All the rest of the magic is normal Ax behavior with bound data controls.
So I hope this is what you needed. Please let me know if you have further questions.

Passing Var type variable from aspx.cs to aspx page

public partial class CityDetailPage : System.Web.UI.Page
{
protected List<CityPhotoGallery> cityPhotoGallery;--It is allowed
protected var cityPhotoGallery; --IT IS NOT ALLOWED
protected void Page_Load(object sender, EventArgs e)
{
}
}
I know how to pass normal variable(whose data Types are known) from aspx.cs page to .aspx page, but in my current senerio a have a var type variable so how i pass this variable to .aspx page from .aspx.cs page
There is no such thing as a var type.
The datatype is either anonymous, e.g. when you use a projection in linq-2-sql or it is the actual datatype derived by the compiler. In that case using var is just shorter.
update
You cannot pass an anonymous type. You just need to use the definite type.
If you want to pass around a projection, you need to create a specific type for that. They are called Poco or DTO (data transfer) object. They function as simple data containers and are used for moving data between the layers of an application
For more information POCO vs DTO

ObjectDataSource+GridView=fires twice

I have a GridView bound to ObjectDataSource. I see, the SelectMethod and the SelectCountMethod are fired twice.
In the GridView RowDataBound I have gv.ShowFooter = false;
When I comment this line, the events are fires only once. Why is that happening? How to work around it? I don't understand, why hiding one element in the databound control results is rebinding the ObjectDataSource?
RowDataBound event gets fired when GridView gets data bound (that means firing of SelectMethod).
Now, toggling properties like ShowFooter requires grid to re-create rows and it means binding the data again. That's why object data source will get triggered again.
Solution will be to set ShowFooter property earlier (instead of RowDataBound). If that's not feasible then put the logic in your object data source class to the cache the data so that you don't have to visit data store twice. For example,
// Code Behind Class
public partial class MyPage : System.Web.UI.Page
{
private object _data;
public static object SelectData()
{
// get the current page instance
var page = HttpContext.Current.CurrentHandler as MyPage;
if (null != page._data)
{
return page._data;
}
// logic to retrieve the data
...
_data = ...
return _data;
}
...
private void RefreshGrid()
{
_data = null; // force the data-source to go to database again
grid.DataBind();
}
}
Disclaimer: un-tested code only for illustration purpose
So, in above code, a static method for page code-behind is used to getting the data. And a local variable in the page class is used for caching the data. Also note for refreshing the grid, you may need to clear the variable before calling DataBind method on grid.

Why is this DropDownList data binding to a List<String> not working?

I'm trying to bind a List<String> to a DropDownList in a user control. I think I'm doing the right thing, but it seems that after my code executes the bindings are cleared. Here's the code for review!
User control:
<asp:DropDownList ID="subjectNameDropDown" runat="server"/>
<asp:DropDownList ID="yearLevelDropDown" runat="server"/>
Auto-generated designed code-behind:
public partial class NewSiteMetadataUserControl {
protected global::System.Web.UI.WebControls.DropDownList subjectNameDropDown;
protected global::System.Web.UI.WebControls.DropDownList yearLevelDropDown;
}
Code-behind:
public partial class NewSiteMetadataUserControl : UserControl
{
protected override void CreateChildControls()
{
subjectNameDropDown = new DropDownList();
yearLevelDropDown = new DropDownList();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
// Attempt 1
List<String> subjectNames = GetSubjectValues();
foreach (var subjectName in subjectNames)
subjectNameDropDown.Items.Add(subjectName);
subjectNameDropDown.DataBind();
// Attempt 2
List<String> yearLevels = GetYearLevelValues();
yearLevelDropDown.DataSource = yearLevels;
yearLevelDropDown.DataBind();
}
}
Should this approach work?
If it should, how can I debug what happens after the code executes?
Yes, this approach should work, here's why it currently isn't,
A DropDownList done with DataBind needs a DataSource. This is why Attempt #1 is not working.
If you're binding to a List<string>, there is no clear key/value pair to bind to. This is why when binding to a List<Person> (for example), you need to override .ToString() in the Person class to provide the key/value binding, or manually set the DataTextField, DataValueField.
There is no way for ASP.NET to work out a key/value pair for a string.
Think about what HTML you want. What should be the key/value for a simple string? Doesn't make sense does it.
Since you don't really care about the "key" (only what is displayed), i suggest you bind to a Dictionary<TKey,TValue> instead.
Either make your method return that, or iterate through the list and add them to the dictionary with an index.
The problem here was CreateChildControls. Somewhere in my attempts to make this work I added this method that initialises the controls. This isn't necessary and in fact caused the data bindings to be wiped out, as it was automatically called by the framework after OnLoad.
The solution was to remove this method and the call to EnsureChildControls.

Reading data from BaseDataBoundControl.DataSource (ASP.NET GridView)

I have an ASP.NET 3.5 GridView on a WebForm.
The GridView gets data from an ObjectDataSource which is set via the DataSourceID property in the code in front.
The ObjectDataSource returns a List of custom data class objects (just a class with public properties) to populate the GridView.
What I want to do is use the a List comsumed by the GridView in another code-behind method. At a high level:
1. GridView is loaded with List data from ObjectDataSource.
2. In the GridView.OnDataBound method I call GridView.DataSource to get the List object.
3. I enumerate the List and use the same data to do some other operation.
The theory being one less duplicated method call and one less call to the back-end database.
I've tried calling DataSource from the GridView' DataBound method and calling GridView.Rows[x].DataItem. In each case I only get a Null reference exception ("Object reference not set to an instance of an object").
Is there any way to achieve what I'm after?
If I understand you correctly, you want the OnRowDataBound event. This way, you can use data from the row that was just databound:
protected void gvGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
CustomDataClass data = e.Row.DataItem as CustomDataClass;
if (data != null)
{
// access data here...
}
}
But do you want the onRowDataBound event? It looks like you want the onDataBound event for the GridView's entire datasource...
So you don't necessarily want one instance (row) of CustomDataClass, you want the entire CustomDataClass[] array of rows to use somewhere else.
HELP! I need this too.
******UPDATE******
I found the answer. Do this as below and set the OnSelected event in your objectdatasource:
protected void ObjectDataSource_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
ObjectListRow[] objectArray = (ObjectListRow[])e.ReturnValue;
List objectList = objectArray.ToList();
}
It turns out my datasource was an array, but if yours is a List<> then just cast the e.ReturnValue as the List.
EASY CHEESY.

Resources