Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm Controls / November 2007

Tip: Looking for answers? Try searching our database.

IDataGridViewEditingControl validation

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Paul S - 12 Nov 2007 14:26 GMT
Hi

I have implemented my own TimeEditorControl:

public class TimeEditorControl : IDataGridViewEditingControl

with the input mask hh:mm. If the user enter ex. 4 and leaves the field, the
value of the control is 4:.
This is of course wrong and gives a problem when the user enters the field
again. I see 2 posibilities:

Prevent the user from leaving a field with bad data or add zeroes to make
the data valid. How do I implement the 2 solutions ?

Thanks
Paul S
Signature

Paul S

Linda Liu[MSFT] - 13 Nov 2007 06:52 GMT
Hi Paul,

It seems that your TimeEditorControl class is derived from the
MaskedTextBox class, right?

If so, you can set the Mask property of the TimeEditorControl to "00:00",
set the PromptChar property to '0' and set the TextMaskFormat property to
IncludePromptAndLiterals, so that the Text property of the
TimeEditorControl returns "04:00" if the user enters 4 and leaves the field.

There is another case, e.g. the user enters "56:34" in the
TimeEditorControl, which is not a valid time. So we should also validate
whether the value the user enters is a valid value of time.

As you have mentioned, there're two kinds of options to choose: preventing
the user from leaving the current cell with bad data or correcting the bad
data automatically.

BTW, from the OOP viewpoint, it would be better to valid the data in the
derived DataGridViewCell class level or in the custom editing control
level, rather than in the DataGridView level.

For the first option, we can do this easily in the DataGridView level, i.e.
handle the CellValidating event of the DataGridView. However, it's hard to
do this in the DataGridViewCell level, because DataGridViewCell class
doesn't expose such an event.

For the second option, we can handle the Leave event of the
TimeEditorControl and if the data is invalid, reset the value to the
default value.

The following is a sample for the second option:

class MyMaskedTextBox : MaskedTextBox,IDataGridViewEditingControl
   {
       DataGridView dataGridView;
       private bool valueChanged = false;
       int rowIndex;

       public MyMaskedTextBox()
       {
           this.TextMaskFormat = MaskFormat.IncludePromptAndLiterals;
           this.PromptChar = '0';
           this.Mask = "00:00";
           this.Leave += new EventHandler(MyMaskedTextBox_Leave);
       }

       void MyMaskedTextBox_Leave(object sender, EventArgs e)
       {
           if(!IsValidHHMM(this.Text))
           {
               this.Text = "00:00";
           }
       }
     
       private bool IsValidHHMM(string text)
       {
           DateTime result;
           bool canParse = DateTime.TryParse(text, out result);
           if (canParse)
               return true;
           else
               return false;
       }

       // Implements the
IDataGridViewEditingControl.EditingControlFormattedValue
       // property.
       public object EditingControlFormattedValue
       {
           get
           {              
               return this.Text;
           }
           set
           {
               String newValue = value as String;
               if (newValue != null)
               {
                   if (IsValidHHMM(newValue))
                   {
                       this.Text = newValue;
                   }
               }
           }
       }

       // Implements the
       // IDataGridViewEditingControl.GetEditingControlFormattedValue
method.
       public object GetEditingControlFormattedValue(
           DataGridViewDataErrorContexts context)
       {
           return EditingControlFormattedValue;
       }

       // Implements the
       // IDataGridViewEditingControl.ApplyCellStyleToEditingControl
method.
       public void ApplyCellStyleToEditingControl(
           DataGridViewCellStyle dataGridViewCellStyle)
       {
           this.Font = dataGridViewCellStyle.Font;
           this.ForeColor = dataGridViewCellStyle.ForeColor;
           this.BackColor = dataGridViewCellStyle.BackColor;
       }

       // Implements the
IDataGridViewEditingControl.EditingControlRowIndex
       // property.
       public int EditingControlRowIndex
       {
           get
           {
               return rowIndex;
           }
           set
           {
               rowIndex = value;
           }
       }

       // Implements the
IDataGridViewEditingControl.EditingControlWantsInputKey
       // method.
       public bool EditingControlWantsInputKey(
           Keys key, bool dataGridViewWantsInputKey)
       {
           // Let the DateTimePicker handle the keys listed.
           switch (key & Keys.KeyCode)
           {
               case Keys.Left:                
               case Keys.Right:
               case Keys.Home:
               case Keys.End:              
                   return true;
               default:
                   return false;
           }          
       }

       // Implements the
IDataGridViewEditingControl.PrepareEditingControlForEdit
       // method.
       public void PrepareEditingControlForEdit(bool selectAll)
       {
           // No preparation needs to be done.
       }

       // Implements the IDataGridViewEditingControl
       // .RepositionEditingControlOnValueChange property.
       public bool RepositionEditingControlOnValueChange
       {
           get
           {
               return false;
           }
       }

       // Implements the IDataGridViewEditingControl
       // .EditingControlDataGridView property.
       public DataGridView EditingControlDataGridView
       {
           get
           {
               return dataGridView;
           }
           set
           {
               dataGridView = value;
           }
       }

       // Implements the IDataGridViewEditingControl
       // .EditingControlValueChanged property.
       public bool EditingControlValueChanged
       {
           get
           {
               return valueChanged;
           }
           set
           {
               valueChanged = value;
           }
       }

       // Implements the IDataGridViewEditingControl
       // .EditingPanelCursor property.
       public Cursor EditingPanelCursor
       {
           get
           {
               return base.Cursor;
           }
       }

       protected override void OnTextChanged(EventArgs e)
       {
           // Notify the DataGridView that the contents of the cell
           // have changed.
           if (EditingControlDataGridView != null)
           {
               valueChanged = true;
               
this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
               base.OnTextChanged(e);
           }
       }      
   }

   public class MaskedTextBoxColumn : DataGridViewColumn
   {
       public MaskedTextBoxColumn()
           : base(new MaskedTextBoxCell())
       {
       }

       public override DataGridViewCell CellTemplate
       {
           get
           {
               return base.CellTemplate;
           }
           set
           {
               // Ensure that the cell used for the template is a
CalendarCell.
               if (value != null &&
                   
!value.GetType().IsAssignableFrom(typeof(MaskedTextBoxCell)))
               {
                   throw new InvalidCastException("Must be a
MaskedTextBoxCell");
               }
               base.CellTemplate = value;
           }
       }
   }

   public class MaskedTextBoxCell : DataGridViewTextBoxCell
   {
     
       public MaskedTextBoxCell()
           : base()
       {          
               
       }
       
       public override void InitializeEditingControl(int rowIndex, object
           initialFormattedValue, DataGridViewCellStyle
dataGridViewCellStyle)
       {
           // Set the value of the editing control to the current cell
value.
           base.InitializeEditingControl(rowIndex, initialFormattedValue,
               dataGridViewCellStyle);
           MyMaskedTextBox ctl = DataGridView.EditingControl as
MyMaskedTextBox;
           if (this.Value != null)
           {
               ctl.Text = this.Value.ToString();
           }
       }

       public override Type EditType
       {
           get
           {
               // Return the type of the editing contol that CalendarCell
uses.
               return typeof(MyMaskedTextBox);
           }
       }

       public override Type ValueType
       {
           get
           {
               // Return the type of the value that CalendarCell contains.
               return typeof(string);
           }
       }

       public override object DefaultNewRowValue
       {
           get
           {
               // Use the current date and time as the default value.
               return "00:00";
           }
       }
   }

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Paul S - 13 Nov 2007 08:44 GMT
Hi Linda
Your solution doesn't prevent the user from leaving the field - how can I
that ?

Just an additional question:

Your sample uses String as ValueType

      public override Type ValueType
       {
           get
           {
               // Return the type of the value that CalendarCell contains.
               return typeof(string);
           }
       }

wouldn't it be more correct to use DateTime or does that course other
problems ?

The DefaultNewRowValue could just return ex. New DateTime(1900, 1,1,0,0,0)
The formatting would display the time part.
Signature

Paul S

> Hi Paul,
>
[quoted text clipped - 296 lines]
> Linda Liu
> Microsoft Online Community Support
Linda Liu[MSFT] - 13 Nov 2007 11:09 GMT
Hi Paul,

> Your solution doesn't prevent the user from leaving the field - how can I
that ?

You're right. If you'd like to prevent the user from leaving the field, you
may subscribe and handle the CellValidating event of the DataGridView. In
the event handler, if the data is invalid, set the
DataGridViewCellValidatingEventArgs.Cancel property to true.

> wouldn't it be more correct to use DateTime or does that course other
problems ?

Yes, I agree with you and using the type of DateTime won't cause any
problem. The following is the modified sample code. Only the
MyMaskedTextBox and MaskedTextBoxCell classes need some modifications.

class MyMaskedTextBox : MaskedTextBox,IDataGridViewEditingControl
{
   ...
   // add a new property called Value, which is of type DateTime
   DateTime datetimevalue;
       public DateTime Value
       {
           set
           {
               if (value.GetType() == typeof(DateTime))
               {
                   String newValue =
Convert.ToDateTime(value).ToString("yyyy/MM/dd HH:mm:ss");
                   this.Text = newValue.Substring(11, 5);
               }
               datetimevalue = value;
           }          
       }
    // modify the EditingControlFormattedValue propery as follows
    public object EditingControlFormattedValue
       {
           get
           {
               string datetimevaluestr =
datetimevalue.ToString("yyyy/MM/dd HH:mm:ss");
               string formattedstring = datetimevaluestr.Substring(0, 11)
+ this.Text + datetimevaluestr.Substring(16, 3);
               return formattedstring;
           }
           set
           {
               if (value.GetType() == typeof(string))
               {                
                   if (DateTime.TryParse(value, out this.datetimevalue))
                   {                        
                       String newvaluestr =
Convert.ToDateTime(newvalue).ToString("yyyy/MM/dd HH:mm:ss");
                       this.Text = newValue.Substring(11, 5);
                   }                  
               }
           }
       }
      ....
}

public class MaskedTextBoxCell : DataGridViewTextBoxCell
{
    public MaskedTextBoxCell()
           : base()
       {
           // set the Format to "t" so that only the time part will be
displayed in the cell
           this.Style.Format = "t";    
       }
      public override void InitializeEditingControl(int rowIndex, object
           initialFormattedValue, DataGridViewCellStyle
dataGridViewCellStyle)
       {
           ...
           if (this.Value != null && this.Value.GetType() ==
typeof(DateTime))
           {
               ctl.Value = Convert.ToDateTime(this.Value);
           }
       }
       public override Type ValueType
       {
           get
           {
               // Return the type of the value that CalendarCell contains.
               return typeof(DateTime);
           }
       }
       public override object DefaultNewRowValue
       {
           get
           {
               // Use the current date and time as the default value.
               return DateTime.Parse("1900/1/1 00:00:00");
           }
       }
       ...
  }

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Paul S - 13 Nov 2007 13:04 GMT
Hi Linda
Thanks - i was hoping to hear you say that I could do some Cancel=true in my
control instead of handling it in the DataGrid. I think i makes my
implementation of the control - not complete !.

Signature

Thanks
Paul S

> Hi Paul,
>
[quoted text clipped - 123 lines]
>  
> This posting is provided "AS IS" with no warranties, and confers no rights.
Linda Liu[MSFT] - 14 Nov 2007 11:21 GMT
Hi Paul,

Thank you for your reply!

After doing more research on this issue, I found a way to prevent the user
from leaving the current cell if the entered value is not valid, i.e.
subscribe the CellValidating event of the referenced DataGridView within
the MyMaskedTextBox class.

The following is the modified complete sample:

class MyMaskedTextBox : MaskedTextBox,IDataGridViewEditingControl
   {
       DataGridView dataGridView;
       private bool valueChanged = false;
       int rowIndex;

       // add a new property called Value, which is of type DateTime
       DateTime datetimevalue;
       public DateTime Value
       {
           set
           {
               if (value.GetType() == typeof(DateTime))
               {
                   String newValue
=Convert.ToDateTime(value).ToString("yyyy/MM/dd HH:mm:ss");
                   this.Text = newValue.Substring(11, 5);
               }
               datetimevalue = value;
           }
       }

       public MyMaskedTextBox()
       {
           this.TextMaskFormat = MaskFormat.IncludePromptAndLiterals;
           this.PromptChar = '0';
           this.Mask = "00:00";          
           
       }
       void dataGridView_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
       {      
           
           if (this.dataGridView.EditingControl != null &&
this.dataGridView.EditingControl.GetType() == typeof(MyMaskedTextBox))
           {
               Console.WriteLine("data grid view cell validating");
               if (!IsValidHHMM(this.Text))
               {                  
                   e.Cancel = true;
               }
           }
       }              
     
       private bool IsValidHHMM(string text)
       {
           DateTime result;
           bool canParse = DateTime.TryParse(text, out result);
           if (canParse)
               return true;
           else
               return false;
       }

       // Implements the
IDataGridViewEditingControl.EditingControlFormattedValue
       // property.
       public object EditingControlFormattedValue
       {
           get
           {
               string datetimevaluestr =datetimevalue.ToString("yyyy/MM/dd
HH:mm:ss");
               string formattedstring = datetimevaluestr.Substring(0, 11)+
this.Text + datetimevaluestr.Substring(16, 3);
               Console.WriteLine("get editing control formatted value:" +
formattedstring);
               return formattedstring;
           }
           set
           {
               if (value.GetType() == typeof(string))
               {
                   if (DateTime.TryParse(value.ToString(), out
this.datetimevalue))
                   {
                       String newvaluestr
=Convert.ToDateTime(this.datetimevalue).ToString("yyyy/MM/dd HH:mm:ss");
                       this.Text = newvaluestr.Substring(11, 5);
                   }
               }
           }

       }

       // Implements the
       // IDataGridViewEditingControl.GetEditingControlFormattedValue
method.
       public object GetEditingControlFormattedValue(
           DataGridViewDataErrorContexts context)
       {
           return EditingControlFormattedValue;
       }

       // Implements the
       // IDataGridViewEditingControl.ApplyCellStyleToEditingControl
method.
       public void ApplyCellStyleToEditingControl(
           DataGridViewCellStyle dataGridViewCellStyle)
       {
           this.Font = dataGridViewCellStyle.Font;
           this.ForeColor = dataGridViewCellStyle.ForeColor;
           this.BackColor = dataGridViewCellStyle.BackColor;
       }

       // Implements the
IDataGridViewEditingControl.EditingControlRowIndex
       // property.
       public int EditingControlRowIndex
       {
           get
           {
               return rowIndex;
           }
           set
           {
               rowIndex = value;
           }
       }

       // Implements the
IDataGridViewEditingControl.EditingControlWantsInputKey
       // method.
       public bool EditingControlWantsInputKey(
           Keys key, bool dataGridViewWantsInputKey)
       {
           // Let the DateTimePicker handle the keys listed.
           switch (key & Keys.KeyCode)
           {
               case Keys.Left:                
               case Keys.Right:
               case Keys.Home:
               case Keys.End:              
                   return true;
               default:
                   return false;
           }          
       }

       // Implements the
IDataGridViewEditingControl.PrepareEditingControlForEdit
       // method.
       public void PrepareEditingControlForEdit(bool selectAll)
       {
           // No preparation needs to be done.
       }

       // Implements the IDataGridViewEditingControl
       // .RepositionEditingControlOnValueChange property.
       public bool RepositionEditingControlOnValueChange
       {
           get
           {
               return false;
           }
       }

       // Implements the IDataGridViewEditingControl
       // .EditingControlDataGridView property.
       public DataGridView EditingControlDataGridView
       {
           get
           {
               return dataGridView;
           }
           set
           {
               dataGridView = value;              
               dataGridView.CellValidating += new
DataGridViewCellValidatingEventHandler(dataGridView_CellValidating);        
       
           }
       }        

       // Implements the IDataGridViewEditingControl
       // .EditingControlValueChanged property.
       public bool EditingControlValueChanged
       {
           get
           {
               return valueChanged;
           }
           set
           {
               valueChanged = value;
           }
       }

       // Implements the IDataGridViewEditingControl
       // .EditingPanelCursor property.
       public Cursor EditingPanelCursor
       {
           get
           {
               return base.Cursor;
           }
       }

       protected override void OnTextChanged(EventArgs e)
       {
           // Notify the DataGridView that the contents of the cell
           // have changed.
           if (EditingControlDataGridView != null)
           {
               valueChanged = true;
               
this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
               base.OnTextChanged(e);
           }
       }      
   }

   public class MaskedTextBoxColumn : DataGridViewColumn
   {
       public MaskedTextBoxColumn()
           : base(new MaskedTextBoxCell())
       {
       }

       public override DataGridViewCell CellTemplate
       {
           get
           {
               return base.CellTemplate;
           }
           set
           {
               // Ensure that the cell used for the template is a
MaskedTextBoxCell.
               if (value != null &&
                   
!value.GetType().IsAssignableFrom(typeof(MaskedTextBoxCell)))
               {
                   throw new InvalidCastException("Must be a
MaskedTextBoxCell");
               }
               base.CellTemplate = value;
           }
       }
   }

   public class MaskedTextBoxCell : DataGridViewTextBoxCell
   {

       public MaskedTextBoxCell()
           : base()
       {
           // set the Format to "t" so that only the time part will be
displayed in the cell
           this.Style.Format = "t";

       }
       
       public override void InitializeEditingControl(int rowIndex, object
           initialFormattedValue, DataGridViewCellStyle
dataGridViewCellStyle)
       {
           // Set the value of the editing control to the current cell
value.
           base.InitializeEditingControl(rowIndex, initialFormattedValue,
               dataGridViewCellStyle);
           MyMaskedTextBox ctl = DataGridView.EditingControl as
MyMaskedTextBox;

           if (this.Value != null && this.Value.GetType() ==
typeof(DateTime))
           {
               ctl.Value = Convert.ToDateTime(this.Value);
           }
           else
           {
               ctl.Value = Convert.ToDateTime(DefaultNewRowValue);
           }
       }

       public override Type EditType
       {
           get
           {
               // Return the type of the editing contol that
MaskedTextBoxCell uses.
               return typeof(MyMaskedTextBox);
           }
       }

       public override Type ValueType
       {
           get
           {
               // Return the type of the value that MaskedTextBoxCell
contains.
               return typeof(DateTime);
           }
       }

       public override object DefaultNewRowValue
       {
           get
           {            
               return DateTime.Parse("1900/1/1 00:00:00");
           }
       }
   }

The above code works well on my side. Please try it in your project to see
if there's any problem and let me know the result.

Sincerely,
Linda Liu
Microsoft Online Community Support
Paul S - 14 Nov 2007 12:08 GMT
It works !
So thanks a lot, Linda.

Just one minor thing I noticed - it doesn't beep when the user tries to
leave the cell with inlvalid data - I could of course just make the beep
myself in the validate event but isn't there a more 'correct' way of doing it
?
Signature

Paul S

> Hi Paul,
>
[quoted text clipped - 296 lines]
>             get
>             {
Linda Liu[MSFT] - 15 Nov 2007 06:11 GMT
Hi Paul,

Thank you for quick feedback!

> it doesn't beep when the user tries to leave the cell with inlvalid data

I don't see it is the default behavior of a DataGridView. But if we edit in
a DataGridViewTextBoxCell in a DataGridView and then press the Esc key, the
DataGridView does beep.

To mimic this behavior, let the MyMaskedTextBox handle the Esc key so that
a beep will be generated when the user presses the Esc key in a
MaskedTextBoxCell which is in edit mode.

As for reminding the user that the data he/she enters in the
MaskedTextBoxCell is invalid, I suggest you show a balloon ToolTip on this
cell.

The following is the modified code based on the sample I provided in my
last reply.

class MyMaskedTextBox : MaskedTextBox,IDataGridViewEditingControl
{
    ...
    // add a ToolTip to remind the user of the invalid data
    ToolTip tooltip = new ToolTip();
    public MyMaskedTextBox()
     {
          ...
          // initialize the ToolTip component
          this.tooltip.IsBalloon = true;
          this.tooltip.ToolTipIcon = ToolTipIcon.Error;
          this.tooltip.ToolTipTitle = "Invaide Time data";
       }
      void dataGridView_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
       {  
           if (this.dataGridView.EditingControl != null &&
this.dataGridView.EditingControl.GetType() == typeof(MyMaskedTextBox))
           {              
               if (!IsValidHHMM(this.Text))
               {
                   e.Cancel = true;
                  // show the ToolTip to remind the user
                   tooltip.Show("", this);
                   tooltip.Show("Please correct the invalid data!", this,
this.Width / 2, this.Height / 2);
               }
               else
               {
                   // hide the ToolTip
                   tooltip.Hide(this);
               }
           }
       }
       // handle the Esc key by ourselves
       protected override void OnKeyDown(KeyEventArgs e)
       {
           base.OnKeyDown(e);
           if (e.KeyCode == Keys.Escape)
           {
               this.dataGridView.CancelEdit();
               this.dataGridView.RefreshEdit();
               this.dataGridView.CurrentCell.DetachEditingControl();
               DataGridViewCell cell = this.dataGridView.CurrentCell;
               this.dataGridView.CurrentCell = null;
               this.dataGridView.CurrentCell = cell;
           }
       }
       public bool EditingControlWantsInputKey(Keys key, bool
dataGridViewWantsInputKey)
       {
           // Let the MyMaskedTextBox handle the keys listed.
          switch (key & Keys.KeyCode)
           {
               case Keys.Left:                
               case Keys.Right:
               case Keys.Home:
               case Keys.End:
               // add this to let the MaskedTextBox handle the Esc key
               case Keys.Escape:
                   return true;
               default:
                   return false;
           }          
       }
       ...
}

Please try it in your project to see if it is what you want and let me know
the result.

Sincerely,
Linda Liu
Microsoft Online Community Support
Linda Liu[MSFT] - 15 Nov 2007 07:10 GMT
Hi Paul,

I found a little problem on the code I gave you just now, i.e. if you edit
in a MaskedTextBoxCell and then edit in a DataGridViewTextBoxCell and then
edit in the previous MaskedTextBoxCell and select another cell at last, an
exception is thrown "Cannot access a dispose object. Object
name:MyMaskedTextBox".

The reason of this problem is that when you first edit in a
MaskedTextBoxCell, DataGridView creates an instance of MyMaskedTextBox and
this instance of MyMaskedTextBox subscribes the CellValidating event of the
DataGridView.

Then you edit in a DataGridViewTextBoxCell and DataGridView creates an
instance of TextBox and disposes the previous instance of MyMaskedTextBox.
Note that the previous instance of MyMaskedTextBox still subscribes the
CellValidating event of the DataGridView.

When you edit in the previous MaskedTextBoxCell for the second time,
DataGridView creates a new instance of MyMaskedTextBox and disposes the
instance of TextBox. Of course, the new instance of MyMaskedTextBox
subscribes the CellValidating event of the DataGridView.

Now if you select another cell, the CellValidating event of the
DataGridView is raised and both the previous instance and new instance of
MyMaskedTextbox are notified and the corresponding event handlers are
executed. The problem is that the previous instance of MyMaskedTextBox has
already been disposed and we cannot access to a disposed object. Thus the
exception is thrown.

To solve this problem, override the Dispose(bool) method in the
MyMaskedTextBox class and unsubscribe the CellValidating event of the
DataGridView. The following is a sample:

class MyMaskedTextBox : MaskedTextBox,IDataGridViewEditingControl
{
    ...
    protected override void Dispose(bool disposing)
       {
           this.dataGridView.CellValidating -= new
DataGridViewCellValidatingEventHandler(dataGridView_CellValidating);
           base.Dispose(disposing);
       }
    ...
}

Hope this helps.

Sincerely,
Linda Liu
Microsoft Online Community Support
Paul S - 15 Nov 2007 07:16 GMT
Thanks a lot for the hint, Linda
Signature

Paul S

> Hi Paul,
>
[quoted text clipped - 47 lines]
> Linda Liu
> Microsoft Online Community Support
Paul S - 14 Nov 2007 12:12 GMT
Hi Linda
Forget about the beep and thanks again for your help
Signature

Paul S

> Hi Paul,
>
[quoted text clipped - 296 lines]
>             get
>             {

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.