2009-12-30 1 views
2

Мне удалось переопределить Boundfield, чтобы отобразить выпадающий список, если я поместил его в Gridview.ASP.NET Boundfield переопределен для поддержки Dropdownlist отсутствует одна окончательная функция

protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState) 
    { 
     Control child = null; 
     Control cellControl = null; 

     if ((((rowState & DataControlRowState.Edit) != DataControlRowState.Normal) && !this.ReadOnly) 
      || ((rowState & DataControlRowState.Insert) != DataControlRowState.Normal)) 
     { 
      // If data cell is in edit mode, create DropDownList editor for this cell 
      // and set data properties. 

      DropDownList box = new DropDownList();     
      box.Items.Add(DefaultValueText);    

      box.DataSource = this.GetDataSource(); 
      box.DataMember = this.BusinessObjectName; 
      box.DataTextField = this.DataTextField; 
      box.DataValueField = this.DataValueField; 
      box.AppendDataBoundItems = true; 
      box.ToolTip = this.HeaderText; 

      cell.Controls.Add(box); 
      box.DataBind(); 
      // if in edit mode, prepare dropdown for binding 
      if ((this.DataField.Length != 0) && ((rowState & DataControlRowState.Edit) != DataControlRowState.Normal)) 
      { 
       cellControl = box; 
      } 
     } 
     else if (this.DataField.Length != 0) // if in read only mode, prepare cell for binding 
     { 
      cellControl = cell; 
     } 

     if ((cellControl != null) && base.Visible) 
     { 
      cellControl.DataBinding += new EventHandler(this.OnDataBindField); 
     } 
    } 


    protected override void OnDataBindField(object sender, EventArgs e) 
    { 
     Control control = (Control)sender; 
     Control namingContainer = control.NamingContainer; 
     object dataValue = this.GetValue(namingContainer); 
     bool encode = (this.SupportsHtmlEncode && this.HtmlEncode) && (control is TableCell); 
     string str = this.FormatDataValue(dataValue, encode); 
     if (control is TableCell) 
     { 
      if (str.Length == 0) 
      { 
       str = " "; 
      } 
      ((TableCell)control).Text = str; 
     } 
     else 
     { 
      //If data cell is in edit mode, set selected value of DropDownList 
      if (dataValue != null) 
      { 
       DropDownList dropDownList = (DropDownList) control; 

       ListItem itm = dropDownList.Items.FindByText(dataValue.ToString()); 
       if (itm != null) 
       { 
        dropDownList.Text = itm.Value; 
       } 
       else 
        ((DropDownList)control).Text = DefaultValueText; 
      } 
     } 
    } 

Последняя особенность, которую я добавил это значение по умолчанию/дополнительный элемент для отображения, если ничего не было выбрано, как «выберите», например. Я могу установить это через свойство DefaultValueText в событии OnDataBind.

Теперь вот проблема я столкнулся:

В InitializeDataCell, если я изложу

box.AppendDataBoundItems = true; 

и называют

box.DataBind(); 

DropDownList имеет все элементы, плюс дополнительные по умолчанию пункт. Он также прекрасно работает в событии OnDataBind, где теперь я могу выбрать значение по умолчанию, если элемент привязки данных не содержит значения.

Но когда DropDownList отображается в GridView, он содержит значение по умолчанию плюс все от источника данных ДВАЖДЫ, потому что я установил AppendDataBoundItems = TRUE, что приводит к ниспадающее меню, чтобы не ясно, что это элементы при добавлении пунктов gridview должен вызывать двойную привязку дважды, но она регистрируется только один раз в методе события OnDataBind. Я вижу только один звонок там, и в этот момент все в порядке, выпадающий список содержит элемент по умолчанию плюс один из каждого элемента из источника данных.

Любые предложения, где и как я могу обрабатывать привязку данных, чтобы иметь полный контроль над привязкой данных?

ответ

2

мне удалось заставить его работать

Я переехал весь код для установки SelectedValue к событию DataBound в DropDownList. В этом случае привязка данных уже произошла, и список значений доступен для меня, чтобы установить selectedValue. Я больше не называю DataBind, так как он все равно вызывается в элементе управления. Я только добавляю элемент «сделать выбор» в начале и устанавливаю для AppendDataBoundItems значение true.

В некоторых состояниях только для чтения могут быть необработанные ситуации, потому что я не обрабатываю события Cell.Databinding().

Полный исходный код для тех, кто заинтересован ...

Он основан на примере из Джавад Zarrinabadi в CodeProjct

использование:

DropDownBoundField dropDownBoundField = new DropDownBoundField(); 
     dropDownBoundField.HeaderText = "NyColumnName"; 
     dropDownBoundField.BusinessObjectName = "BusinessLogic.MyDataClass"; 
     dropDownBoundField.SelectMethod = "GetEnumerable"; 
     dropDownBoundField.DataTextField = "Name"; // what should be displayed 
     dropDownBoundField.DataValueField = "Id"; // value behind the displayed text 
     dropDownBoundField.DataField = "IdProperty"; // Property to bind to 
     dropDownBoundField.DefaultValueText = "Select"; // text on first item as 
                 default if DataField is null    
     dropDownBoundField.FindBy = SetSelectedValueBy.Value // Choose how the DataField is being evaluated, as source for the value or the text 
     GridView.Columns.Add(dropDownBoundField); 

Класс:

using System; 
using System.Web.UI.WebControls; 
using System.Web.UI; 
using System.ComponentModel; 
using System.Web; 
using System.Collections.Specialized; 

namespace IDVCode.GridViews 
{ 
public class DropDownField : BoundField 
{ 
    #region fields 
    private string _listDataSourceID; 
    private string _listDataMember; 
    private string _listDataTextField; 
    private string _listDataValueField; 
    #endregion 

    #region eventHandler 

    protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState) 
    { 
      DropDownList dropDownList = new DropDownList(); 
      dropDownList.ToolTip = HeaderText; 
      dropDownList.DataSourceID = ListDataSourceID; 
      dropDownList.DataMember = ListDataMember; 
      dropDownList.DataTextField = ListDataTextField; 
      dropDownList.DataValueField = ListDataValueField; 
      dropDownList.Enabled = !ReadOnly; 
      cell.Controls.Add(dropDownList); 

      if (rowState == DataControlRowState.Normal || rowState == DataControlRowState.Alternate || ReadOnly) 
      { 
       dropDownList.Enabled = false; 
      } 
      if (DataField.Length != 0) // && ((rowState & DataControlRowState.Edit) != DataControlRowState.Normal)) 
      { 
       dropDownList.DataBound += new EventHandler(OnDataBindField); 
      } 
     } 

    protected override void OnDataBindField(object sender, EventArgs e) 
    { 
     Control control = (Control)sender; 
     Control namingContainer = control.NamingContainer; 
     object dataValue = GetValue(namingContainer); 
     bool encode = (SupportsHtmlEncode && HtmlEncode) && (control is TableCell); 
     string str = FormatDataValue(dataValue, encode); 
     if (control is TableCell) 
     { 
      if (str.Length == 0) 
      { 
       str = " "; 
      } 
      ((TableCell)control).Text = str; 
     } 
     else 
     { 
      if (!(control is DropDownList)) 
      { 
       throw new HttpException("BoundField_WrongControlType"); 
      } 
      if (((DropDownList)control).Items.Count > 0) // Don't call selectedValue if empty 
      { 
       if (dataValue != null) 
       { 
        DropDownList dropDownList = (DropDownList)control; 

        ListItem item = null; 
        if (FindBy == SetSelectedValueBy.Value) 
        { 
         item = dropDownList.Items.FindByValue(dataValue.ToString()); 
        } 
        else 
        { 
         item = dropDownList.Items.FindByText(dataValue.ToString()); 
        } 

        if (item != null) 
         dropDownList.Text = item.Value; 
        else 
        { 
         ListItem defaultItem = dropDownList.Items.FindByText(DefaultValueText); 
         if (defaultItem != null) 
          dropDownList.SelectedValue = defaultItem.Value; 
        } 
       } 
      } 
     } 
    } 

    public override void ExtractValuesFromCell(IOrderedDictionary dictionary, DataControlFieldCell cell, 
     DataControlRowState rowState, bool includeReadOnly) 
    { 
     Control control = null; 
     string dataField = DataField; 
     object text = null; 
     string nullDisplayText = NullDisplayText; 
     if (((rowState & DataControlRowState.Insert) == DataControlRowState.Normal) || InsertVisible) 
     { 
      if (cell.Controls.Count > 0) 
      { 
       control = cell.Controls[0]; 
       DropDownList box = control as DropDownList; 
       if (box != null) 
       { 
        text = box.SelectedValue; 
       } 
      } 
      else if (includeReadOnly) 
      { 
       string s = cell.Text; 
       if (s == " ") 
       { 
        text = string.Empty; 
       } 
       else if (SupportsHtmlEncode && HtmlEncode) 
       { 
        text = HttpUtility.HtmlDecode(s); 
       } 
       else 
       { 
        text = s; 
       } 
      } 
      if (text != null) 
      { 
       if (((text is string) && (((string)text).Length == 0)) && ConvertEmptyStringToNull) 
       { 
        text = null; 
       } 
       if (((text is string) && (((string)text) == nullDisplayText)) && (nullDisplayText.Length > 0)) 
       { 
        text = null; 
       } 
       if (dictionary.Contains(dataField)) 
       { 
        dictionary[dataField] = text; 
       } 
       else 
       { 
        dictionary.Add(dataField, text); 
       } 
      } 
     } 
    } 

    #endregion 

    #region Properties 

    public virtual string ListDataSourceID 
    { 
     get 
     { 
      if (_listDataSourceID == null) 
      { 
       object stateBag = ViewState["ListDataSourceID"]; 
       if (stateBag != null) 
       { 
        _listDataSourceID = (string)stateBag; 
       } 
       else 
       { 
        _listDataSourceID = string.Empty; 
       } 
      } 
      return _listDataSourceID; 
     } 
     set 
     { 
      if (!object.Equals(value, ViewState["ListDataSourceID"])) 
      { 
       ViewState["ListDataSourceID"] = value; 
       _listDataSourceID = value; 
       OnFieldChanged(); 
      } 
     } 
    } 

    public virtual string ListDataMember 
    { 
     get 
     { 
      if (_listDataMember == null) 
      { 
       object stateBag = ViewState["ListDataMember"]; 
       if (stateBag != null) 
       { 
        _listDataMember = (string)stateBag; 
       } 
       else 
       { 
        _listDataMember = string.Empty; 
       } 
      } 
      return _listDataMember; 
     } 
     set 
     { 
      if (!object.Equals(value, ViewState["ListDataMember"])) 
      { 
       ViewState["ListDataMember"] = value; 
       _listDataMember = value; 
       OnFieldChanged(); 
      } 
     } 
    } 

    public virtual string ListDataTextField 
    { 
     get 
     { 
      if (_listDataTextField == null) 
      { 
       object stateBag = ViewState["ListDataTextField"]; 
       if (stateBag != null) 
       { 
        _listDataTextField = (string)stateBag; 
       } 
       else 
       { 
        _listDataTextField = string.Empty; 
       } 
      } 
      return _listDataTextField; 
     } 
     set 
     { 
      if (!object.Equals(value, ViewState["ListDataTextField"])) 
      { 
       ViewState["ListDataTextField"] = value; 
       _listDataTextField = value; 
       OnFieldChanged(); 
      } 
     } 
    } 

    public virtual string ListDataValueField 
    { 
     get 
     { 
      if (_listDataValueField == null) 
      { 
       object stateBag = ViewState["ListDataValueField"]; 
       if (stateBag != null) 
       { 
        _listDataValueField = (string)stateBag; 
       } 
       else 
       { 
        _listDataValueField = string.Empty; 
       } 
      } 
      return _listDataValueField; 
     } 
     set 
     { 
      if (!object.Equals(value, ViewState["ListDataValueField"])) 
      { 
       ViewState["ListDataValueField"] = value; 
       _listDataValueField = value; 
       OnFieldChanged(); 
      } 
     } 
    } 

    [Description("Sets a default value if applicable")] 
    [Category("Appearance")] 
    public string DefaultValueText 
    { 
     get 
     { 
      object val = ViewState["DefaultValueText"]; 
      if (val != null) 
      { 
       return (string)val; 
      } 
      return (string.Empty); 
     } 

     set 
     { 
      ViewState["DefaultValueText"] = value; 
     } 
    } 

    [Description("Defines how the SelectedValue is set")] 
    [Category("Data")] 
    [DefaultValue(SetSelectedValueBy.Value)] 
    public SetSelectedValueBy FindBy 
    { 
     get 
     { 
      object val = ViewState["SetSelectedValueBy"]; 
      return val != null ? (SetSelectedValueBy) val : SetSelectedValueBy.Value; 
     } 
     set 
     { 
      ViewState["SetSelectedValueBy"] = value; 
     } 
    } 

    public enum SetSelectedValueBy 
    { 
     Text, 
     Value 
    } 

    #endregion 
} 

}

0

Ну, я знаю, что в некоторых ситуациях он связывается несколько раз (при изменении критериев и т. Д.), Поэтому вы снова будете иметь дело с этой проблемой ... можете ли вы очистить список и переустановить?

+0

Единственный способ я вижу, чтобы повлиять на привязку данных является привязка обработчика события к DropDownList.DataBind ING. И это называется только один раз (из того, что я вижу в режиме отладки), так кто же копирует элементы во второй раз? Методы getModes(), связанные с выпадающим списком, получают количество обращений, эквивалентное количеству строк, которые у меня есть (один раз для каждого инициализированного списка выпадающего списка). Может ли это быть из вида? Думаю, я мог бы попытаться отключить это, если возможно –