ComboBox custom web/server-side control - where's the data?
-
I wrote a custom combobox server control that inherited the webcontrols.listbox class so that I'd get all of the built-in list handling features. Then I added a textbox to allow me to type in a value that wasn't in the listbox, and some client-side javascript to set the textbox to the selected item in the list when one was clicked, select a matching item in the list when one was typed into the textbox, or to set the list's selectedIndex to -1 when the value typed into the textbox didn't match. All of this works fine. The problem is that when the form posts back I don't see any of the data I expected, not the list selection, nor the textbox value. As I said I expected the list selection to be returned automatically, but I didn't actually use that instance, opting instead to use a span container with the a textbox, another listbox, and an imagebutton added to the span's controls, then rendered from the span level. So, how do I get the data to post-back from these sub-controls? I really don't want to use the original list that my control inherited, as I need the span container to make my control work in absolute position mode. However, to make my control work in non-absolute position mode, when the textbox's width is set to auto, I don't always render the span, instead I simply render the controls below the span and let the browser work out all of the widths. Thank you in advance.
-
I wrote a custom combobox server control that inherited the webcontrols.listbox class so that I'd get all of the built-in list handling features. Then I added a textbox to allow me to type in a value that wasn't in the listbox, and some client-side javascript to set the textbox to the selected item in the list when one was clicked, select a matching item in the list when one was typed into the textbox, or to set the list's selectedIndex to -1 when the value typed into the textbox didn't match. All of this works fine. The problem is that when the form posts back I don't see any of the data I expected, not the list selection, nor the textbox value. As I said I expected the list selection to be returned automatically, but I didn't actually use that instance, opting instead to use a span container with the a textbox, another listbox, and an imagebutton added to the span's controls, then rendered from the span level. So, how do I get the data to post-back from these sub-controls? I really don't want to use the original list that my control inherited, as I need the span container to make my control work in absolute position mode. However, to make my control work in non-absolute position mode, when the textbox's width is set to auto, I don't always render the span, instead I simply render the controls below the span and let the browser work out all of the widths. Thank you in advance.
Using the following code I can see my data:
Dim CBX1 As cwcComboBox.cwcComboBox = Me.cwcComboBox1 Dim CBX1Value As String Dim CBX1Values As String() CBX1Value = CBX1.Page.Request.Params.Get(CBX1.ID) CBX1Values = CBX1.Page.Request.Params.GetValues(CBX1.ID)
CBX1Value = "Three,3", CBX1Values(0)="Three", and CBX1Values(1)="3" So the data is there. However, when I try to access the data the "correct" way by declaring a LoadPostData function as follows:
Public Function LoadPostData( ByVal Key As String, ByVal PostData As NameValueCollection ) As Boolean _
Implements IPostBackDataHandler.LoadPostData
:
End FunctionThe compiler says that IPostBackDataHandler is not implemented by this class, but my custom component inherits from the ListBox webcontrol. So at the top of my class, after the inherits statement, I tried using:
Implements System.Web.UI.IPostBackDataHandler
But the compiler says its already implemented by the listbox base class, which seems to disagree with the earlier compiler error! Anyone know what's going on with this?
-
Using the following code I can see my data:
Dim CBX1 As cwcComboBox.cwcComboBox = Me.cwcComboBox1 Dim CBX1Value As String Dim CBX1Values As String() CBX1Value = CBX1.Page.Request.Params.Get(CBX1.ID) CBX1Values = CBX1.Page.Request.Params.GetValues(CBX1.ID)
CBX1Value = "Three,3", CBX1Values(0)="Three", and CBX1Values(1)="3" So the data is there. However, when I try to access the data the "correct" way by declaring a LoadPostData function as follows:
Public Function LoadPostData( ByVal Key As String, ByVal PostData As NameValueCollection ) As Boolean _
Implements IPostBackDataHandler.LoadPostData
:
End FunctionThe compiler says that IPostBackDataHandler is not implemented by this class, but my custom component inherits from the ListBox webcontrol. So at the top of my class, after the inherits statement, I tried using:
Implements System.Web.UI.IPostBackDataHandler
But the compiler says its already implemented by the listbox base class, which seems to disagree with the earlier compiler error! Anyone know what's going on with this?
Here is an important missing piece that needs to be added after the inherits statement:
Implements INamingContainer
Now I no longer get the conflicting messages, only one that says:
'System.Web.UI.IPostBackDataHandler.LoadPostData' is already implemented by base class 'System.Web.UI.WebControls.ListBox' and cannot be implemented again.
So now my question is how do I override or shadow the one in the base class so I can capture the rest of the data that my component sends back? My component is a combobox, and should send back the TextBox value and the ListBox Index. Even if getting the LoadPostData to work, it isn't clear to me how you get both of these data values out of it. The example code I've seen so far says that the Key value is the name of my component, which is used as an index in the NameValueCollection paramenter, so it seems to only be set up to get one value. Also, since I have two values, which one will it get?
-
Here is an important missing piece that needs to be added after the inherits statement:
Implements INamingContainer
Now I no longer get the conflicting messages, only one that says:
'System.Web.UI.IPostBackDataHandler.LoadPostData' is already implemented by base class 'System.Web.UI.WebControls.ListBox' and cannot be implemented again.
So now my question is how do I override or shadow the one in the base class so I can capture the rest of the data that my component sends back? My component is a combobox, and should send back the TextBox value and the ListBox Index. Even if getting the LoadPostData to work, it isn't clear to me how you get both of these data values out of it. The example code I've seen so far says that the Key value is the name of my component, which is used as an index in the NameValueCollection paramenter, so it seems to only be set up to get one value. Also, since I have two values, which one will it get?
This is a work around that I used after I got some help from Sebastián Streiger after posting a similar question on his article's feedback:
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs) MyBase.OnInit(e) Try If Page.IsPostBack() Then ' The page can have many instances of this component, so don't want to push the ' cwcComboBoxInfo state class instance infomation through the ViewState, so put ' a reference to in a session variable, actually done at the end of the Render ' Sub. ' ' When the page is posted back, the component state is restored by setting the cwcComboBoxInfo to the reference value saved in the session variable. ' If Not HttpContext.Current.Session(cwcComboBoxInfo.ID) Is Nothing Then cwcComboBoxInfo = CType(HttpContext.Current.Session(cwcComboBoxInfo.ID), cwcComboBoxInfoClass) End If ' Get the postback data. LoadPostData() ' There is a bug in VS.NET 2003 that prevents the LoadPostData ' function from overriding/shadowing the listbox base class's ' IPostBackDataHandler.LoadPostData and RaisePostDataChangeEvent ' implementation, so call the LoadPostData function directly to ' get the posted data. End If Catch Ex As Exception Throw New cwcComboBoxException("OnLoad: Exception - Component " & Me.ID & ", " & _ Ex.Message) End Try End Sub ' ------------------------------------------------------------- ' The following was a suggested fix to the IPostBackDataHandler implmentation problem, but ' it didn't seem to help. Instead, Sebastián Streiger suggested that the Impments ... ' statement should be removed from the LoadPostData function and RaisePostDataChangeEvent Sub ' declarations. However, while this allowed me to compile the code it doesn't seem to get ' called by the .NET Framework. So I implmemented a override LoadPostData function with no ' parameters that I directly call from the OnLoad event sub above. Public Shadows Interface IPostBackDataHandler Function LoadPostData(ByVal sPostData