Thursday, November 27, 2008

ASPxCallback && ASPxCallbackPanel

I was to do a web form for filling site information in some regions. To do that, i must select Province/City first in ComboBox and then a Region/District that belongs to the Province/City respectively; means when i select Province in combobox1, only regions in that province must be retrieved from server to combobox2.

I use Developer Express components regularly and if i used the latest versions of DevXpress ASPx components, it would be made easy by using ASPxCallbackPanel. But my DevXpress version is DevX 7.2 and there is no ASPxCallbackPanel component as is MS AJAX UpdatePanel. So i solved it with ASPxCallback component.

site_main.aspx:

<dxcb:aspxcallback id="ASPxCallback1" runat="server" clientinstancename="Callback1" oncallback="ASPxCallback1_Callback"></dxcb:aspxcallback>
<clientsideevents callbackcomplete="function(s, e) { var items= e.result.split("|") var i; for (i= 0; i< items[0]; i++) { cbbRegion.AddItem(items[2*i+ 2], items[2*i+ 1]); } }"></clientsideevents>



<dxe:aspxcombobox id="cbbCity" runat="server" height="19px" width="100px" datasourceid="dsrcCity" textfield="city_name" valuefield="city_code"></dxe:aspxcombobox>
<clientsideevents selectedindexchanged="function(s, e) { //alert(s.GetValue()); cbbRegion.ClearItems(); Callback1.SendCallback(s.GetValue()); }"></clientsideevents>


<asp:objectdatasource id="dsrcCity" runat="server" oldvaluesparameterformatstring="original_{0}" selectmethod="GetData" typename="CdsCityTableAdapters.vw_cityTableAdapter"></asp:objectdatasource>



<dxe:aspxcombobox id="cbbRegion" runat="server" clientinstancename="cbbRegion" datasourceid="dsrcRegion" textfield="region_name" valuefield="region_code" width="120px"></dxe:aspxcombobox>

<asp:objectdatasource id="dsrcRegion" runat="server" deletemethod="Delete" insertmethod="Insert" oldvaluesparameterformatstring="original_{0}" selectmethod="GetDataByCity" typename="CdsRegionTableAdapters.hr_regionTableAdapter" updatemethod="Update"></asp:objectdatasource>
<deleteparameters></deleteparameters>
<asp:parameter name="Original_region_id" type="Decimal"></asp:parameter>

<updateparameters></updateparameters>
<asp:parameter name="region_code" type="String"></asp:parameter>
<asp:parameter name="region_name" type="String"></asp:parameter>
<asp:parameter name="city_code" type="String"></asp:parameter>
<asp:parameter name="Original_region_id" type="Decimal"></asp:parameter>

<selectparameters></selectparameters>
<asp:parameter name="city_code" type="String"></asp:parameter>

<insertparameters></insertparameters>
<asp:parameter name="region_code" type="String"></asp:parameter>
<asp:parameter name="region_name" type="String"></asp:parameter>
<asp:parameter name="city_code" type="String"></asp:parameter>



<dxe:aspxmemo id="mmAntenna" runat="server" height="74px" width="729px"></dxe:aspxmemo>

site_main.aspx.cs:
protected void ASPxCallback1_Callback(object source, DevExpress.Web.ASPxCallback.CallbackEventArgs e)
{
CdsRegionTableAdapters.hr_regionTableAdapter regionTableAdapter = new CdsRegionTableAdapters.hr_regionTableAdapter();
CdsRegion.hr_regionDataTable regionDataTable= new CdsRegion.hr_regionDataTable();
regionTableAdapter.FillByCity(regionDataTable, e.Parameter);
String res = regionDataTable.Rows.Count.ToString();
for (int i = 0; i < regionDataTable.Rows.Count; i++)
{
res = res + "|"+ regionDataTable.Rows[i]["region_code"]+ "|"+ regionDataTable.Rows[i]["region_name"]+ "";
}
e.Result = res;
}

The mechanic is, when selected a city, selectedindexchanged="function(s, e) { //alert(s.GetValue()); cbbRegion.ClearItems(); Callback1.SendCallback(s.GetValue()); } is called. In it, cbbRegion is cleaned up and value of cbbCity is sent to server. Then, on server, ASPxCallback1_Callback is called and it sends corresponding "|" separated region names and codes back to the client using e.Result string. After that, callbackcomplete="function(s, e) { var items= e.result.split("|") var i; for (i= 0; i< items[0]; i++) { cbbRegion.AddItem(items[2*i+ 2], items[2*i+ 1]); } } is called automatically. As you see, the function parses e.Result and adds each to cbbRegion. I think the way i used is not good. But it was working so quick. I prefer coding style, but when result is good, it's ok to hardcode kk.