2009-12-30 84 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; 
      } 
     } 
    } 

的最後一項功能我加是如果沒有被選中,如「請選擇」,例如顯示默認值/附加項目。我可以通過OnDataBind事件中的屬性DefaultValueText來設置它。

現在,這裏是我面臨的問題:

在InitializeDataCell,如果我設置

box.AppendDataBoundItems = true; 

,並呼籲

box.DataBind(); 

的下拉列表擁有的所有項目,加上其他默認項目。 它也可以在OnDataBind事件中很好地工作,如果數據綁定項不包含值,我現在可以選擇默認值。

但是,當顯示在GridView的下拉列表,它包含了從數據源的缺省值加兩遍,因爲我設置AppendDataBoundItems = true,這會導致不明確它的項目添加項目時,下拉 的gridview必須調用數據綁定兩次,但它只在OnDataBind事件方法中註冊一次。我只在那裏看到一個電話,在那一刻,一切都很好,下拉菜單中包含默認項目加上數據源中每個項目的一個。

任何建議我在哪裏或如何處理數據綁定,以便我完全控制數據綁定?

回答

2

我設法得到它的工作

我感動了所有的代碼爲了selectedValue設置將DropDownList的DataBound事件。在這種情況下,數據綁定已經發生,值的列表可供我設置selectedValue。我不再調用DataBind,因爲它在控件上被調用。我只在開頭添加「make a selection」項並將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()方法接收的命中數等於我擁有的行數(每個dropdownlist初始化一次)。 它可能來自視圖狀態?如果可能的話,我想我可能會嘗試關閉它 – 2009-12-30 11:36:58