Adding a CheckBox column to your DataGrid

Sample Image - checkgrid.jpg

Introduction

There are many articles that explain how to add controls to a DataGrid that can be used to represent and edit data in a format other than a common EditBox, however they all appear to require the programmer to edit the html in the .aspx page(s) rather than use code held solely in the .cs Codebehind files. I have in the past had to implement many different controls that can be used to represent and edit controls within a DataGrid and here I will demonstrate the CheckBox template column with bound CheckBoxes as it is one of the simplest but the the most used control other then the EditBox, and is used to edit fields that are of the boolean type.

ITemplate implementation

Before we can implement the class that will be used as a column within our DataGrid, a class that derives from ITemplate will need to be created that can be used for representing and or editing the data within the grid. In most cases a seperate class will need to be defined for displaying and editing, eg containing a label control or an edit box control. Fortunately we can use the same control, a CheckBox, to represent the boolean state as well as edit it.

public CheckBoxItem(bool editable)
{
    readOnly = (editable==true)?false:true;
}

Handling the DataBinding event

Because the CheckBox control is to represent data that is held in the DataGrid then it will need to handle the DataBinding event, which will be called once for each row in the DataGrid. This can be set up in the InstantiateIn method implementation which is the one and only method of the ITemplate interface.

void ITemplate.InstantiateIn(Control container)
{
    CheckBox box = new CheckBox();
    box.DataBinding += new EventHandler(this.BindData);
    container.Controls.Add(box);
}

Processing the DataBinding event

The handler for the DataBinding event is used to set the state of the control depending on the data within the underlying DataGrid as well as set the editable state depending on whether it is being used to view the data or edit the data.

public void BindData(object sender, EventArgs e)
{
    CheckBox box = (CheckBox) sender;
    DataGridItem container = (DataGridItem) box.NamingContainer;
    box.Checked = false;
    box.Enabled = (readOnly == true) ? false:true;
    string data = ((DataRowView) container.DataItem)[dataField].ToString();
    Type type = ((DataRowView)
    container.DataItem).DataView.Table.Columns[dataField].DataType;
    if (data.Length>0)
    {
        switch (type.ToString())
        {
        case "System.Boolean":
            if ( data == "True")
            {
                box.Checked = true;
            }
            break;
        default:
            break;
        }
    }
}

CheckBox Template Column

The class that will be used as the column in our DataGrid will be derived from the System.Web.UI.WebControls.TemplateColumn class. We add objects of the above ITemplate implementation class to the ItemTemplate property, for display, and EditItemTemplate property, for editing.

public CheckBoxColumn()
{
    // set the view one as readonly
    viewItem = new CheckBoxItem(false);
    this.ItemTemplate = viewItem as ITemplate;

    // let the edit check box be editable
    editItem = new CheckBoxItem(true);
    this.EditItemTemplate = editItem as ITemplate;
}

Adding the Column to the DataGrid

The penultimate step is to add the column to the DataGrid itself. Because of the way we have designed the class this is simplicity itself as it can be used in place of a BoundColumn.

CheckBoxColumn checkCol = new CheckBoxColumn();
checkCol.HeaderText = "Boolean Field (Editable)";
checkCol.DataField = "Boolean";

...

DataGrid1.Columns.Add(checkCol);

Extracting the Updated State

The final step is extracting the data from the control itself when it comes to updating or inserting a row. Again we use a similar method as that normally employed however instead of a TextBox we use a CheckBox.

sqlUpdateCommand1.Parameters["@Boolean"].Value
             = ((CheckBox)e.Item.Cells[4].Controls[0]).Checked;

AutoPostBack and receiving the CheckedChanged event

It was recently asked if it was possible to receive the CheckedChanged event from the CheckBoxes that were contained within the column. I have since updated the code to handle the scenario where you have a DataGrid with a CheckGridColumn and it is possible to update the field immediately.

Sample Image - checkgrid2.jpg

To add a column to our DataGrid that handles this sceanrio we do the following.

CheckBoxColumn checkCol2 = new CheckBoxColumn(true);
checkCol2.HeaderText = "Boolean Field (Always Editable)";
checkCol2.DataField = "Boolean";

// this is our handler for all of the CheckBoxes CheckedChanged events
checkCol2.CheckedChanged += new EventHandler(this.OnCheckChanged); 

...

DataGrid2.Columns.Add(checkCol2);
Now because we need to handle the event to change our database entry we need to extract the relevent information from the DataGrid as well as extract the state of the CheckBox. The following sample shows how this could be done.
private void OnCheckChanged(object sender, EventArgs e)
{
	CheckBox box = (CheckBox) sender;
	DataGridItem container = (DataGridItem) box.NamingContainer;

	// get our values
	sqlUpdateCommand1.Parameters["@Object_id"].Value
                                = int.Parse(container.Cells[0].Text);
	sqlUpdateCommand1.Parameters["@Boolean"].Value = box.Checked;

...

}

Documentation

The code has been documented using the /// documentation syntax. I prefer to use NDOC which can be found at Sourceforge for my Documentation generation engine. It also handles all those tags that Microsoft created and then forgot about.

Article History

29 July 2002 - Original Article Posted
03 Sept 2002 - Updated Article with Commented Source Code

Feedback

Your feedback is important to me and I am always willing to make improvements. If you found this article useful don't forget to vote.

</body></html>

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

 

CheckColumn.cs

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

namespace ManyMonkeys.Web.DataGrid.ColumnTemplates
{
 public class CheckBoxColumn :System.Web.UI.WebControls.TemplateColumn
 {
  /// <summary>
  /// Initialise our CheckBoxColumn.
  /// </summary>
  public CheckBoxColumn()
  {
   // set the view one as readonly
   viewItem = new CheckBoxItem(false); // SAW was false
   this.ItemTemplate = viewItem as ITemplate;

   // let the edit check box be editable
   editItem = new CheckBoxItem(true);
   this.EditItemTemplate = editItem as ITemplate;
  }

  /// <summary>
  /// Initialise our CheckBoxColumn with an optional ImmediatePostback capability.
  /// </summary>
  /// <param name="ImmediatePostback">If true then each change of state of the CheckBox item
  /// will cause an event to be fired immediately on the server.</param>
  public CheckBoxColumn(bool ImmediatePostback)
  {
   // set the view one as readonly
   viewItem = new CheckBoxItem(ImmediatePostback);
   this.ItemTemplate = viewItem as ITemplate;

   // let the edit check box be editable
   editItem = new CheckBoxItem(true);
   this.EditItemTemplate = editItem as ITemplate;

   AutoPostBack = ImmediatePostback;
  }

  /// <summary>
  /// Occurs when the value of the Checked property changes between posts to the server.
  /// </summary>
  /// <remarks>
  /// The <b>CheckedChanged</b> event is raised when the value of the Checked property changes between posts to the server.
  ///
  /// <b>Note</b>   This event does not post the page back to the server unless the AutoPostBack property is set to true.
  /// <b>Note</b>   The control must have viewstate enabled for the <b>CheckedChanged</b> event to work correctly.
  /// </remarks>
  public event EventHandler CheckedChanged
  {
   add
   {
    viewItem.CheckedChanged += value;
    editItem.CheckedChanged += value;
   }
   remove
   {
    viewItem.CheckedChanged -= value;
    editItem.CheckedChanged -= value;
   }
  }

  /// <summary>
  /// If true then then each click on a CheckBox will cause an event to be fired on the server.
  /// </summary>
  public bool AutoPostBack
  {
   set
   {
    viewItem.AutoPostBack = value;
    editItem.AutoPostBack = value;
   }
   get
   {
    return viewItem.AutoPostBack;
   }
  }

  /// <summary>
  /// The DataField that we wish our control to bind to.
  /// </summary>
  public string DataField
  {
   get
   {
    return viewItem.DataField;
   }
   set
   {
    viewItem.DataField = value;
    editItem.DataField = value;
   }
  }

  /// <summary>
  /// Internal storage of the CheckBoxItem that is to be used for the view state.
  /// </summary>
  private CheckBoxItem viewItem;

  /// <summary>
  /// Internal storage of the CheckBoxItem that is to be used for the edit state.
  /// </summary>
  private CheckBoxItem editItem;
 }
}
CheckItem.cs

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

namespace ManyMonkeys.Web.DataGrid.ColumnTemplates
{
 internal class CheckBoxItem : ITemplate
 {
  /// <summary>
  /// The CheckBoxItem constructor
  /// </summary>
  /// <param name="editable">true if the item is to be in its editable state, false for the item to be disabled.</param>
  public CheckBoxItem(bool editable)
  {
   readOnly = (editable==true)?false:true;
  }

  /// <summary>
  /// Instantiates the CheckBox that we wish to represent in this column.
  /// </summary>
  /// <param name="container">The container into which the control or controls are added.</param>
  void ITemplate.InstantiateIn(Control container)
  {
   CheckBox box = new CheckBox();
   box.DataBinding += new EventHandler(this.BindData);
   box.AutoPostBack = autoPostBack;
   box.CheckedChanged += new EventHandler(this.OnCheckChanged);
   container.Controls.Add(box);
  }

  /// <summary>
  /// Our CheckChanged event
  /// </summary>
  public event EventHandler CheckedChanged;

  /// <summary>
  /// This is a common handler for all the Checkboxes.
  /// </summary>
  /// <param name="sender">The raiser of this event a CheckBox.</param>
  /// <param name="e">A System.EventArgs that contains the event data.</param>
  private void OnCheckChanged(object sender, EventArgs e)
  {
   if (CheckedChanged != null)
   {
    CheckedChanged(sender, e);
   }
  }

  /// <summary>
  /// The internal storage for which DataField we are going to represent.
  /// </summary>
  private string dataField;

  /// <summary>
  /// Used to set the DataField that we wish to represent with this CheckBox.
  /// </summary>
  public string DataField
  {
   get
   {
    return dataField;
   }
   set
   {
    dataField=value;
   }
  }

  /// <summary>
  /// The internal storage for the AutoPostback flag.
  /// </summary>
  private bool autoPostBack=false;

  /// <summary>
  /// Set the AutoPostBack flag. If this is true then each time a CheckBox is clicked
  /// in the Column that contains this item then an event is raised on the server.
  /// </summary>
  public bool AutoPostBack
  {
   set
   {
    autoPostBack = value;
   }
   get
   {
    return autoPostBack;
   }
  }

  /// <summary>
  /// Handler for the DataBinding event where we bind the data for a specific row
  /// to the CheckBox.
  /// </summary>
  /// <param name="sender">The raiser of the event.</param>
  /// <param name="e">A System.EventArgs that contains the event data.</param>
  private void BindData(object sender, EventArgs e)
  {
   CheckBox box = (CheckBox) sender;
   DataGridItem container = (DataGridItem) box.NamingContainer;
   box.Checked = false;
   box.Enabled = (readOnly == true) ? false:true;
   string data = ((DataRowView) container.DataItem)[dataField].ToString();
   Type t = ((DataRowView)container.DataItem).DataView.Table.Columns[dataField].DataType;
   if (data.Length>0)
   {
    switch (t.ToString())
    {
     case "System.Boolean":
      if (( data == "True") || (data == "true"))
      {
       box.Checked = true;
      }
      break;
     default:
      break;
    }
   }
  }

  /// <summary>
  /// Internal storage for the readOnly flag.
  /// </summary>
  private bool readOnly = true;
 }
}

To add custom functions to the NX menu, you can use the NXOpen.MenuBar class in NXOpen.NET API. Here is an example code that demonstrates how to add a custom function to the NX menu: ```vb Imports System Imports NXOpen Module Module1 Sub Main() ' Get the NX session Dim theSession As Session = Session.GetSession() ' Get the UI work part Dim theUI As UI = theSession.UI Dim lw As ListingWindow = theSession.ListingWindow ' Get the menu bar Dim menuBar As MenuBar = theUI.MenuBar ' Get the File menu Dim fileMenu As Menu = menuBar.GetMenu("File") ' Add a separator to the File menu fileMenu.AddSeparator() ' Add a custom function to the File menu Dim menuItem As MenuItem = fileMenu.AddMenuItem("Custom Function", AddressOf CustomFunction) ' Show a message box when the custom function is clicked Sub CustomFunction(ByVal item As MenuItem) lw.Open() lw.WriteLine("Custom function is clicked!") lw.Close() End Sub ' Start the NX message loop to display the menu theUI.NXMessageBox.Show("Menu Example", NXMessageBox.DialogType.Information, "Click OK to display the menu") theUI.NXMessageBox.GetMessage() ' Remove the custom function from the menu fileMenu.RemoveMenuItem(menuItem) End Sub End Module ``` In the above code, we first obtain the NX session and UI work part. Then, we get the MenuBar object using `theUI.MenuBar`. Next, we retrieve the desired menu (e.g., "File") using `GetMenu()` method. We can add a separator using `AddSeparator()` method and add a custom function using `AddMenuItem()` method, specifying the function to be called when the menu item is clicked. In the example above, the `CustomFunction` is a sub that will be executed when the custom function menu item is clicked. You can customize the behavior of this function to perform your desired actions. After adding the custom function, we start the NX message loop using `theUI.NXMessageBox.Show()` and `theUI.NXMessageBox.GetMessage()` to display the menu. Finally, we remove the custom function from the menu using `RemoveMenuItem()` method. Please note that above code is just an example, and you may need to adjust it based on your specific requirements and menu structure in NX.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值