Question

I've got a Telerik.WinControls.UI.RadGridView with multiple columns in it. I'm using a mix of rowvalidation and cellvalidation to validate the input I get (although for the current problem I also tried deactivating the rowvalidation but still got the same results).

I have one daterow for which I use the cellvalidating event to validate it (else I get an exception if a user types in a wrong date). The behaviour I expected was that the error message is displayed and the cell not validated. The 2nd thing worked, but the error message ONLY gets displayed when I move the mouse onto the border of the cell (else it is just not shown).

So my question would be how could I manage to achieve that the error message is shown as soon and as long as an error is found through the validation?

Here is the cellvalidation code I use:

void MainFormGridView_CellValidating(object sender, CellValidatingEventArgs eventArgs)
{
    var currentCell = eventArgs.Row.Cells[eventArgs.ColumnIndex];

    if (eventArgs.Column.Name == "OrderDate")
    {
        if (eventArgs.Value == null)
        {
            eventArgs.Cancel = true;
        }
        else
        {
            try
            {
                DateTime dateValue;
                if (!DateTime.TryParse(eventArgs.Value.ToString(), out dateValue))
                {
                    eventArgs.Cancel = true;
                }
            }
            catch
            {
                // Error occured so validation error!
                eventArgs.Cancel = true;
            }
        }
        if (eventArgs.Cancel)
        {
            currentCell.ErrorText = "Error no valid date! Please type in a valid date";
        }
        else
        {
            currentCell.ErrorText = string.Empty;
        }
    }
}
Was it helpful?

Solution 3

In order to manage to print the tooltip and have it visible while the mouse is over the cell a few things need to be done. Be aware that my grid is called myGrid in the example source while the form is called myForm.

The first thing that we need to do is defining 2 helper variables we need:

private ToolTip _tooltip;
private Point _mouse;

Then we need to define the tooltip, and need to define a custom handler for the event we need

public myForm()
{
    InitializeComponent();
    ....//your additional initialization code

    _tooltip = new ToolTip();
    this.myGrid.CellEditorInitialized += myGrid_CellEditorInitialized;
    this.myGrid.CellValidating+= myGrid_CellValidating;
}

The code for the cell validating is quite simple:

private void myGrid_CellValidating(object sender, CellValidatingEventArgs e)
{
    string errorText = string.Empty;
    // Are we really on a column currently?
    if (e.ColumnIndex >= 0)
    {
        if (e.Value == null)
        {
             errorText = "No field may be empty";
        }
    }

    // Has an error occured? If so don't let the user out of the field until its corrected!
    if (errorText != string.Empty)
    {
        e.Cancel = true;
    }
    e.Row.ErrorText = errorText;
    e.Row.Cells[e.Column.Name].ErrorText = errorText;
}

After this is done we need to make sure that when the celleditor is initialized, that the tooltip is made ready in case it is needed:

private void myGrid_CellEditorInitialized(objec sender, GridViewCellEventArgs e)
{
                RadTextBoxEditor radTextBoxEditor = e.ActiveEditor as RadTextBoxEditor;
                RadTextBoxEditorElement editorElement = radTextBoxEditor.EditorElement as RadTextBoxEditorElement;
                editorElement.AutoToolTip = true;  
                TextBox myTextBox= (TextBox)editorElement.TextBoxItem.HostedControl;  

                myTextBox.MouseMove -= new MouseEventHandler(textBox_MouseMove);  
                myTextBox.MouseLeave -= new EventHandler(textBox_MouseLeave); 
                myTextBox.MouseMove += new MouseEventHandler(textBox_MouseMove);  
                myTextBox.MouseLeave += new EventHandler(textBox_MouseLeave);  
}

Thus first we get the "textbox" of the editor (regardless what type of editor is really there) and set the events we will need for this textbox, as we want to know when the user has the mouse over the textbox, and when not.

The next step is to define the mousemove function, thus WHEN shall the tooltip be displayed:

void textBox_MouseMove(object sender, MouseEventArgs e)  
{ 
    if (mousePos != e.Location)  
    { 
        RadTextBoxEditor radTextBoxEditor = this.myGrid.ActiveEditor as RadTextBoxEditor;
        GridDataCellElement gridCellElement = radTextBoxEditor.OwnerElement as GridDataCellElement;
        if (gridCellElement != null && gridCellElement.ContainsErrors)
        {
            RadTextBoxEditorElement radTextBoxEditorElement = radTextBoxEditor.EditorElement as RadTextBoxEditorElement;
            TextBox myTextBox = (TextBox)radTextBoxEditorElement.TextBoxItem.HostedControl;  
            _tooltip.Show(gridCellElement.RowInfo.Cells[gridCellElement.ColumnInfo.Name].ErrorText, myTextBox, new Point(e.Location.X + 8, e.Location.Y + 8));  
            _mouse = e.Location;  
        }
    }
}

After this we also need to let the tooltip disappear again which we do with the mouseleave event:

void textBox_MouseLeave(object sender, EventArgs e)  
        { 
            RadTextBoxEditor radTextBoxEditor = this.myGrid.ActiveEditor as RadTextBoxEditor;
            RadTextBoxEditorElement radTextBoxEditorElement = radTextBoxEditor.EditorElement as RadTextBoxEditorElement;
            TextBox myTextBox = (TextBox)radTextBoxEditorElement.TextBoxItem.HostedControl;  
            Rectangle textBoxBounds = new Rectangle(myTextBox.PointToScreen(Point.Empty), myTextBox.Size);  
            if (!textBoxBounds.Contains(Control.MousePosition))
            { 
                _tooltip.Hide(textBox);  
            }
        }

With these steps done we have a tooltip that appears when the user moves the mouse into the cell and disappears again when he leaves the cell.

OTHER TIPS

Find an event that gets triggered when you mouse over the cell and fire it from your code if there are validation errors. Not the most elegant solution yet it should work.

I'm using Telerik WPF RadGridView controls, yet it's still the windows namespace, give this a try.

/// <summary>
/// RadGridView cell validating.
/// </summary>
/// <param name="e">
/// The e.
/// </param>
private void CellValidating(GridViewCellValidatingEventArgs e)
{
  bool isValid = true;
  string validationText = "Validation failed. ";
  GridViewCell cell = e.Cell;
  switch (cell.Column.UniqueName)
  {
    case "Code":
    case "Name":
    case "County":
    case "Region":
      isValid = e.NewValue != null && !string.IsNullOrWhiteSpace(e.NewValue.ToString());
      if (!isValid)
      {
        validationText += string.Format("{0} is required.", cell.Column.UniqueName);
      }

      break;

      /* Continue case statements... */

  }

  if (!isValid)
  {
    MarkCell(cell, validationText);
  }
  else
  {
    RestoreCell(cell);
  }

  e.ErrorMessage = validationText;
  e.IsValid = isValid;
}

/// <summary>
/// Marks the cell with a red box and tooltip of the validation text.
/// </summary>
/// <param name="cell">
/// The cell.
/// </param>
/// <param name="validationText">
/// The validation text.
/// </param>
private void MarkCell(Control cell, string validationText)
{
  ToolTipService.SetToolTip(cell, validationText);
}

/// <summary>
/// Restores the cell and removes the tooltip.
/// </summary>
/// <param name="cell">
/// The cell.
/// </param>
private void RestoreCell(Control cell)
{
  ToolTipService.SetToolTip(cell, null);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top