Ajax AutoCompleteExtender стилизира отделни елементи?

Кратка версия:

Искам да знам как мога да променя css стила на отделни елементи, генерирани от autocompleteextender, но контролата ми позволява само да задам стила на всички елементи като група.

Дълга версия:

Имам поле за търсене, което използва AutoCompleteExtender. Докато пишете, резултатите от търсенето изскачат в поле под полето за търсене.

<asp:TextBox ID="txtSearch" OnChange="javascript: Changed(this);"  runat="server" style="width:360px;" />
<cc1:AutoCompleteExtender ID="Search_AutoCompleteExtender" runat="server" 
                    BehaviorID="Search_AutoCompleteExtender"
                    MinimumPrefixLength="3" 
                    DelimiterCharacters="" 
                    Enabled="True" 
                    ServicePath="~/Services/Search.asmx" 
                    ServiceMethod="GetResults"
                    TargetControlID="txtSearch"
                    FirstRowSelected="true"
                    CompletionListItemCssClass="AutoExtenderList"
                    CompletionListHighlightedItemCssClass="AutoExtenderHighlight"
                    CompletionInterval="1" 
                    EnableCaching="false"
                    CompletionSetCount="20"
                    CompletionListElementID="autocompleteDropDownPanel1" />

<asp:Panel ID="autocompleteDropDownPanel1" runat="server" ScrollBars="Vertical" Height="250" style="overflow-y:scroll;position:absolute;left:0;top:0" /

AutoCompleteExtender има свойство за присвояване на CSS клас на всеки елемент, CompletionListItemCssClass и CompletionListHighlightedItemCssClass за маркирания елемент. Това, което искам да знам, е как мога индивидуално да стилизирам конкретни елементи въз основа на определени критерии.

В моята услуга изпълнявам съхранена процедура, като манипулирам малко резултатите, след което връщам низов масив обратно към autocompleteextender. Имам тази съхранена процедура, настроена да включва определен флаг с всеки запис.. Искам да използвам този флаг, за да маркирам определени редове от резултатите от търсенето (например да оцветя текста в червено).

Как мога да направя това? Изглежда не мога да намеря начин за достъп до отделни елементи, за да променя стила им.

Търсих помощ навсякъде и идвам с празни ръце. Благодаря ти.


person user1003916    schedule 21.09.2012    source източник


Отговори (1)


Такова поведение не се поддържа по подразбиране, но можете да настроите източниците на AutoCompleteExtender, за да добавите тази функция. Всъщност има два налични начина: първият е да се разшири обект, върнат на разширителя от уеб услугата с ново свойство за css клас на елемент и да се приложи тази стойност на свойство в клиентския скрипт на разширителя. И вторият достъпен подход е да се въведе ново събитие за създаване на елемент, да се обработи на страницата и да се приложи персонализирана логика към елемент в зависимост от неговата стойност. Нека приложим и двата подхода тук. Първо трябва да изтеглите източниците на AjaxControlToolkit, ако все още не сте го направили, и да отворите Client/MicrosoftAjax.Extended/AutoComplete/AutoCompleteBehavior.pre.js файл. В този файл трябва да промените метода _update, както е показано по-долу:

_update: function (prefixText, completionItems, cacheResults) {
    /// <summary>
    /// Method to update the status of the autocomplete behavior
    /// </summary>
    /// <param name="prefixText" type="String" DomElement="false" mayBeNull="true" />
    /// <param name="completionItems" type="Object" DomElement="false" mayBeNull="true" />
    /// <param name="cacheResults" type="Object" DomElement="false" mayBeNull="true" />
    /// <returns />       
    if (cacheResults && this.get_enableCaching()) {
        if (!this._cache) {
            this._cache = {};
        }
        this._cache[prefixText] = completionItems;
    }

    // If the target control loses focus or 
    // if the value in textbox has changed before the webservice returned
    // completion items we don't need to show popup 
    if ((!this._textBoxHasFocus) || (prefixText != this._currentCompletionWord())) {
        this._hideCompletionList();
        return;
    }

    if (completionItems && completionItems.length) {
        this._completionListElement.innerHTML = '';
        this._selectIndex = -1;
        var _firstChild = null;
        var text = null;
        var value = null;
        var cssClass = null;
        var dataItem = null;

        //remove this line if you don't need to implement itemDataBinding event
        var itemDataBindingHandler = this.get_events().getHandler('itemDataBinding');

        for (var i = 0; i < completionItems.length; i++) {
            // Create the item                
            var itemElement = null;
            if (this._completionListElementID) {
                // the completion element has been created by the user and li won't necessarily work
                itemElement = document.createElement('div');
            } else {
                itemElement = document.createElement('li');
            }

            // set the first child if it is null
            if (_firstChild == null) {
                _firstChild = itemElement;
            }

            // Get the text/value for the item
            try {
                dataItem = Sys.Serialization.JavaScriptSerializer.deserialize( completionItems[i] );
                if (dataItem && dataItem.First) {
                    // Use the text and value pair returned from the web service
                    text = dataItem.First;
                    value = dataItem.Second;

                    if (dataItem.CssClass) {
                        cssClass = dataItem.CssClass;
                    }
                }
                else {
                    // If the web service only returned a regular string, use it for
                    // both the text and the value
                    text = completionItems[i];
                    value = text;
                }
            } catch (ex) {
                text = completionItems[i];
                value = completionItems[i];
            }


            // Set the text/value for the item
            // ShowOnlyCurrentWordInCompletionListItem support
            var optionText = this._showOnlyCurrentWordInCompletionListItem ? text : this._getTextWithInsertedWord(text);
            itemElement.appendChild(document.createTextNode(optionText));
            itemElement._value = value;
            itemElement.__item = '';

            if (this._completionListItemCssClass) {
                Sys.UI.DomElement.addCssClass(itemElement, this._completionListItemCssClass);
            } else {
                var itemElementStyle = itemElement.style;
                itemElementStyle.padding = '0px';
                itemElementStyle.textAlign = 'left';
                itemElementStyle.textOverflow = 'ellipsis';
                // workaround for safari since normal colors do not
                // show well there.
                if (Sys.Browser.agent === Sys.Browser.Safari) {
                    itemElementStyle.backgroundColor = 'white';
                    itemElementStyle.color = 'black';
                } else {
                    itemElementStyle.backgroundColor = this._textBackground;
                    itemElementStyle.color = this._textColor;
                }
            }

            if (cssClass) {
                Sys.UI.DomElement.addCssClass(itemElement, cssClass);   
            }

            //remove this if you don't need to implement itemDataBinding event
            if (itemDataBindingHandler) {
                itemDataBindingHandler(itemElement, dataItem || completionItems[i]);
            }

            this._completionListElement.appendChild(itemElement);
        }
        var elementBounds = $common.getBounds(this.get_element());
        this._completionListElement.style.width = Math.max(1, elementBounds.width - 2) + 'px';
        this._completionListElement.scrollTop = 0;

        this.raisePopulated(Sys.EventArgs.Empty);

        var eventArgs = new Sys.CancelEventArgs();
        this.raiseShowing(eventArgs);
        if (!eventArgs.get_cancel()) {
            this.showPopup();
            // Check if the first Row is to be selected by default and if yes highlight it and updated selectIndex.
            if (this._firstRowSelected && (_firstChild != null)) {
                this._highlightItem(_firstChild);
                this._selectIndex = 0;
            }
        }
    } else {
        this._hideCompletionList();
    }
}

Ако не възнамерявате да приложите сценарий с ново събитие от страна на клиента, това са всички промени в проекта, от които се нуждаете. Вече можете да предавате css клас на елемент от метода на уеб сървъра заедно с текста и стойността на елемента. Единствената разлика е да се използва персонализиран клас вместо двойката, която се използва в контролата на AjaxControlToolkit по подразбиране:

[WebMethod]
public string[] GetCompletionList(string prefixText, int count)
{
    var serializer = new JavaScriptSerializer();
    var items = Enumerable.Range(1, count)
        .Select(id => serializer.Serialize(
                        new
                        {
                            Second = id,
                            First = prefixText + "_" + Guid.NewGuid().ToString(),
                            CssClass = id % 2 == 0 ? "even" : "odd"
                        }));


    return items.ToArray();
}

АКО искате да приложите и персонализирано клиентско събитие (което наистина дава повече гъвкавост), тогава трябва да добавите още малко код към файла AutoCompleteBehavior.pre.js. Добавете код по-долу някъде в Sys.Extended.UI.AutoCompleteBehavior.prototype обект:

add_itemDataBinding: function (handler) {
    this.get_events().addHandler('itemDataBinding', handler);
},

remove_itemDataBinding: function (handler) {
    this.get_events().removeHandler('itemDataBinding', handler);
},

Освен това отворете файла Server/AjaxControlToolkit/AutoComplete/AutoCompleteExtender.cs и добавете това свойство към класа AutoCompleteExtender:

/// <summary>
/// Handler to attach to the client-side item data binding event
/// </summary>
[DefaultValue("")]
[ExtenderControlEvent]
[ClientPropertyName("itemDataBinding")]
public string OnClientItemDataBinding
{
    get { return GetPropertyValue("OnClientItemDataBinding", string.Empty); }
    set { SetPropertyValue("OnClientItemDataBinding", value); }
}

След възстановяване на проекта можете да използвате персонализиран сбор на AjaxControlToolkit с допълнителна функционалност.

<script type="text/javascript">
    function itemDataBinding(item, dataItem) {
        var value = parseInt(dataItem.Second, 10);
        if (!isNaN(value)) {
            item.className = value % 2 == 0 ? "even" : "odd";
        }
    }
</script>

<ajaxToolkit:AutoCompleteExtender runat="server" ID="autoComplete1" 
    TargetControlID="myTextBox" ServicePath="AutoComplete.asmx" ServiceMethod="GetCompletionList" 
    OnClientItemDataBinding="itemDataBinding">
person Yuriy Rozhovetskiy    schedule 21.09.2012
comment
Това е един от най-добрите отговори, които съм виждал. Благодаря много, че отделихте време да ми помогнете. - person user1003916; 24.09.2012