Templated control and load on demand not working

5 posts, 0 answers
  1. Thomas
    Thomas avatar
    143 posts
    Member since:
    Feb 2007

    Posted 03 Apr 2008 Link to this post

    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.

  2. Thomas
    Thomas avatar
    143 posts
    Member since:
    Feb 2007

    Posted 03 Apr 2008 Link to this post

    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?

  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Veselin Vasilev
    Admin
    Veselin Vasilev avatar
    2992 posts

    Posted 04 Apr 2008 Link to this post

    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
  5. Thomas
    Thomas avatar
    143 posts
    Member since:
    Feb 2007

    Posted 04 Apr 2008 Link to this post

    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

  6. Veselin Vasilev
    Admin
    Veselin Vasilev avatar
    2992 posts

    Posted 07 Apr 2008 Link to this post

    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
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017