This is a migrated thread and some comments may be shown as answers.

Templated control and load on demand not working

4 Answers 202 Views
ComboBox
This is a migrated thread and some comments may be shown as answers.
Thomas
Top achievements
Rank 1
Thomas asked on 04 Apr 2008, 12:43 AM
I'm trying to setup a RadComboBox control to use load on demand. In addition, the control is configured to use a template like so:
<telerik:RadComboBox ID="CurrencyEdit" runat="server" Width="55px" DropDownWidth="300px"  
    ShowToggleImage="true" ShowMoreResultsBox="true" EnableVirtualScrolling="true" 
    Height="200px" DataValueField="ISOCode" DataTextField="ISOCode" EnableLoadOnDemand="True" 
    OnItemsRequested="CurrencyEdit_ItemsRequested"
    <HeaderTemplate> 
        <table > 
            <colgroup> 
                <col width="60px" /> 
                <col width="270px" /> 
            </colgroup> 
            <tr> 
                <td> 
                    <asp:Literal ID="CurrencyISOCodeLabel" runat="server" meta:resourcekey="CurrencyISOCodeLabel" /></td
                <td> 
                    <asp:Literal ID="CurrencyNameLabel" runat="server" meta:resourcekey="CurrencyNameLabel" /></td
            </tr> 
        </table> 
    </HeaderTemplate> 
    <ItemTemplate> 
        <table style="border: solid 1px FFFF; font: menu; font-size: small; color: Black;"
            <colgroup> 
                <col width="60px" /> 
                <col width="270px" /> 
            </colgroup> 
            <tr> 
                <td> 
                    <%# DataBinder.Eval(Container.DataItem, "ISOCode") %> 
                </td> 
                <td> 
                    <%# DataBinder.Eval(Container.DataItem, "Name") %> 
                </td> 
            </tr> 
        </table> 
    </ItemTemplate> 
</telerik:RadComboBox> 
 


If I use something like:
MyControl.DataSource = MyCollection;
MyControl.DataBind();

The control populates fine. However, if I use something like the following, the RadComboBox shows an empty result. It sees that it has items thanks to the message, but the results themselves are empty.


protected void CurrencyEdit_ItemsRequested( object o, RadComboBoxItemsRequestedEventArgs e ) 
    int itemsPerRequest = 10; 
    int itemOffSet = e.NumberOfItems; 
    int endOffset = itemOffSet + itemsPerRequest; 
 
    CurrencyBinder binder = new CurrencyBinder(); 
    CurrencyCollection currencies = binder.Find( e.Text ); 
 
    if ( endOffset > currencies.Count ) 
        endOffset = currencies.Count; 
 
    e.EndOfItems = endOffset == currencies.Count; 
 
    for ( int i = itemOffSet; i < endOffset; i++ ) 
    { 
        Currency currency = currencies[i]; 
        this.CurrencyEdit.Items.Add( new RadComboBoxItem( currency.ISOCode, currency.ISOCode ) ); 
    } 
 
    if ( currencies.Count > 0 ) 
    { 
        e.Message = string.Format( "Items <b>1</b>-<b>{0}</b> out of <b>{1}</b>" 
            , endOffset 
            , currencies.Count ); 
    } 
    else 
    { 
        e.Message = "No matches"
    } 
 


Note that CurrencyCollection is simply a collection of custom Currency objects with a property of ISOCode representing its standard three letter representation.

4 Answers, 1 is accepted

Sort by
0
Thomas
Top achievements
Rank 1
answered on 04 Apr 2008, 01:35 AM
Ok. I have resolve much of the problem. The binding issue was solved by changing the ItemTemplate binding to the following:

<td> 
    <%# DataBinder.Eval( Container, "Value" )%> 
</td> 
<td> 
    <%# DataBinder.Eval( Container, "Text" )%> 
</td> 


In addition, I needed to call DataBind on the RadComboBox control so my ItemsRequest method changed to:
protected void CurrencyEdit_ItemsRequested( object o, RadComboBoxItemsRequestedEventArgs e ) 
    int itemsPerRequest = 10; 
    int itemOffSet = e.NumberOfItems; 
    int endOffset = itemOffSet + itemsPerRequest; 
 
    CurrencyBinder binder = new CurrencyBinder(); 
    CurrencyCollection currencies = binder.Find( e.Text ); 
 
    if ( endOffset > currencies.Count ) 
        endOffset = currencies.Count; 
 
    e.EndOfItems = endOffset == currencies.Count; 
 
    for ( int i = itemOffSet; i < endOffset; i++ ) 
    { 
        Currency currency = currencies[i]; 
        this.CurrencyEdit.Items.Add( new RadComboBoxItem( currency.Name, currency.ISOCode ) ); 
    } 
 
    Currency selectedCurrency = new Currency(); 
    selectedCurrency.Get( this.CurrencyEdit.SelectedValue ); 
 
    if ( !currencies.Contains( selectedCurrency ) ) 
        this.CurrencyEdit.Items.Insert( 0, new RadComboBoxItem( selectedCurrency.Name, selectedCurrency.ISOCode ) ); 
 
    if ( this.CurrencyEdit.Items.Count > 0 ) 
        this.CurrencyEdit.DataBind(); 
 
    if ( currencies.Count > 0 ) 
    { 
        e.Message = string.Format( "Items <b>1</b>-<b>{0}</b> out of <b>{1}</b>" 
            , endOffset 
            , currencies.Count ); 
    } 
    else 
    { 
        e.Message = "No matches"
    } 
 

Note that I needed to employ a couple of tricks. The first was to ensure that I had RadComboBoxItems before I called DataBind. If I did not, then I got a "Index out of Range" error which I suspect was due to the fact that on loading the page, the RadComboBox's Text and Value properties were set. In addition, I had to insert the existing selected item for the same reason.

However, now I'm running into a issue with AutoComplete. I have MarkFirstMatch enabled through a skin. The problem is that MarkFirstMatch marks based on the Text property as opposed to the Value property. If I understand how the RadComboBox works, if I swap the values (i.e. put the ISO code in the Text property and the Name in the Value property), will it not balk on selection? In addition, on closing the RadCombo I want to display the much shorter ISO code instead of the full blown currency name.

Any ideas?

0
Veselin Vasilev
Telerik team
answered on 04 Apr 2008, 01:41 PM
Hi Thomas,

Thank you for writing to us and your question!

You are right - when Templates are defined in the ComboBox, the DataBind() method should be called explicitly.

MarkFirstMatch property gets or sets a value indicating whether the combobox should automatically autocomplete and highlight the currently typed text to the closest item text match.

You can subscribe to the OnClientDropDownClosing event and alert whatever property you want for the currently selected item.

Sincerely yours,
Veskoni
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Thomas
Top achievements
Rank 1
answered on 04 Apr 2008, 03:28 PM
I found the solution last night. The trick is to put the other data you want in Attributes instead of the Value property. So the ItemsRequested event looks like:

        protected void CurrencyEdit_ItemsRequested( object o, RadComboBoxItemsRequestedEventArgs e ) 
        { 
            int itemsPerRequest = 10; 
            int itemOffSet = e.NumberOfItems; 
            int endOffset = itemOffSet + itemsPerRequest; 
 
            CurrencyBinder binder = new CurrencyBinder(); 
            CurrencyCollection currencies = binder.Find( e.Text ); 
 
            if ( endOffset > currencies.Count ) 
                endOffset = currencies.Count; 
 
            e.EndOfItems = endOffset == currencies.Count; 
 
            for ( int i = itemOffSet; i < endOffset; i++ ) 
            { 
                Currency currency = currencies[i]; 
                RadComboBoxItem item = new RadComboBoxItem( currency.ISOCode, currency.ISOCode ); 
                item.Attributes.Add( "Name", currency.Name ); 
                this.CurrencyEdit.Items.Add( item ); 
            } 
 
            Currency selectedCurrency = new Currency(); 
            if ( string.IsNullOrEmpty( this.CurrencyEdit.SelectedValue ) ) 
            { 
                selectedCurrency.ISOCode = string.Empty; 
                selectedCurrency.Name = Resources.AvailsResources.NoneSelected; 
            } 
            else if ( !selectedCurrency.Get( this.CurrencyEdit.SelectedValue ) ) 
            { 
                throw new ApplicationException( string.Format( Resources.AvailsResources.CannotFindItem 
                    , typeof( Currency ), this.CurrencyEdit.SelectedValue ) ); 
            } 
 
            if ( !TelerikUtility.RadComboBoxContainsValue( this.CurrencyEdit, selectedCurrency.ISOCode ) ) 
            { 
                RadComboBoxItem item = new RadComboBoxItem( selectedCurrency.ISOCode, selectedCurrency.ISOCode ); 
                item.Attributes.Add( "Name", selectedCurrency.Name ); 
 
                this.CurrencyEdit.Items.Insert( 0, item ); 
            } 
 
            if ( this.CurrencyEdit.Items.Count > 0 ) 
                this.CurrencyEdit.DataBind(); 
 
            if ( currencies.Count > 0 ) 
            { 
                e.Message = string.Format( "Items <b>1</b>-<b>{0}</b> out of <b>{1}</b>" 
                    , endOffset 
                    , currencies.Count ); 
            } 
            else 
            { 
                e.Message = "No matches"
            } 
        } 

Another part of the trick was to ensure that the value I was adding did not already exist in the list of items since they can get appended through VirtualScrolling. That is what my TelerikUtility.RadComboBoxContainsValue utility function does. Through a quick search with Reflector, it did not appear that the RadComboBoxItem implemented a custom Equals method nor that the Contains method on the RadComboBoxItemCollection had any special logic which I believe means that it simply uses ObjectRef to do comparisons.

The markup now changed to:
<td> 
    <%# DataBinder.Eval( Container, "Text" )%> 
</td> 
<td> 
    <%# DataBinder.Eval( Container, "Attributes['Name']" )%> 
</td> 
 

Now autocomplete works as expected since both the Text and Value properties have the same data. Now, I'd like to encapsulate this logic into its own server control. I have broken this request out into a separate thread at:

Creating a derived server control

0
Veselin Vasilev
Telerik team
answered on 07 Apr 2008, 08:09 AM
Hello Thomas,

Thank you for sharing your solution with the Community!

I believe it will be useful to the members.

Greetings,
Veskoni
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
Tags
ComboBox
Asked by
Thomas
Top achievements
Rank 1
Answers by
Thomas
Top achievements
Rank 1
Veselin Vasilev
Telerik team
Share this question
or