This is a migrated thread and some comments may be shown as answers.

IDataErrorInfo and Validation

36 Answers 735 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Deborah
Top achievements
Rank 1
Deborah asked on 18 Oct 2010, 11:52 PM
We are binding our grids to a BindingList<T> where T is a business object that implements IDataErrorInfo.

How do we "hook up" data validation in the GridView in this case?

When we had it bound to the Microsoft DataGridView we did not have to do anything. The error icons automatically appeared in the cell using the text defined using the IDataErrorInfo properties. But this does not appear to work with the GridView?

I read through what I could find on validation in the documentation and it appeared to require writing code in the Validating events. Is this still required when the binding source uses IDataErrorInfo?

Thanks!

36 Answers, 1 is accepted

Sort by
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 12:25 AM
Hi Deborah,

Perhaps this link will help

Let me know if you need more info
Richard
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 01:51 AM
We don't have row headers on.

Is there a way to show the icon in the cell itself?
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 07:36 AM
Hi Deborah,

Yes, you'd need to use the CellFormatting event to inspect the Cell.ContainsErrors property and then set an image in the cell accordingly.

For exmaple:

VB
Private Sub radGridView1_CellFormatting(sender As Object, e As CellFormattingEventArgs) handles radGridView1.CellFormatting
    Dim cell As GridDataCellElement = TryCast(e.CellElement, GridDataCellElement)
    If cell IsNot Nothing Then
        If cell.ContainsErrors Then
            cell.DrawBorder = True
            cell.BorderBoxStyle = BorderBoxStyle.SingleBorder
            cell.BorderWidth = 2
            cell.BorderColor = Color.Red
            cell.ImageAlignment = ContentAlignment.MiddleRight
            cell.Image = ' image
        End If
    End If
End Sub


C#
void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)
{
    GridDataCellElement cell = e.CellElement as GridDataCellElement;
    if (cell != null)
    {
        if (cell.ContainsErrors)
        {
            cell.DrawBorder = true;
            cell.BorderBoxStyle = BorderBoxStyle.SingleBorder;
            cell.BorderWidth = 2;
            cell.BorderColor = Color.Red;
              
            cell.Image = //image;
            cell.ImageAlignment = ContentAlignment.MiddleRight; 
         }     
    }
}
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 03:41 PM
So the CelllFormatting event is my only choice?

When I tried this, the border only appeared around the cell when I was on the line with the error. I want the border to appear always.

Here is the scenario: User enters three new rows, with errors in each one. I want to show all of the errors, not just the errors in the row that the user was in.

Is there a way to get the border color to *stay* red until the error is correct?
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 03:56 PM
It should stay red, though I did miss out the else. 
Give this a try please Deborah

Private Sub radGridView1_CellFormatting(sender As Object, e As CellFormattingEventArgs) handles Me.radGridView1.CellFormatting
    Dim cell As GridDataCellElement = TryCast(e.CellElement, GridDataCellElement)
    If cell IsNot Nothing Then
        If cell.ContainsErrors Then
            cell.DrawBorder = True
            cell.BorderBoxStyle = BorderBoxStyle.SingleBorder
            cell.BorderWidth = 2
            cell.BorderColor = Color.Red
         cell.ImageAlignment = ContentAlignment.MiddleRight
         cell.Image = ' image
        Else
            cell.ResetValue(LightVisualElement.DrawBorderProperty, ValueResetFlags.Local)
            cell.ResetValue(LightVisualElement.BorderBoxStyleProperty, ValueResetFlags.Local)
            cell.ResetValue(LightVisualElement.BorderWidthProperty, ValueResetFlags.Local)
            cell.ResetValue(LightVisualElement.BorderColorProperty, ValueResetFlags.Local)
        End If
    End If
End Sub
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 04:07 PM
Except for setting the image, that is pretty much what I had.

I will spend some more time on this later today and get back to you on my results.

THANKS!
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 04:12 PM
No problem Deborah. 
Just try it on any cell. 
For example, instead of inspecting for cell.ContainsErrors, you can test by looking for the Text value of a specific cell (just for testing). 
You should see that the border stays on all the time when it reaches the condition and goes away when you change the cell text. 

let me know if you need anything else. Also, may I ask that you mark as answer if you find this works for you so others can quickly find the solution. 

Best wishes
Richard
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 04:44 PM
I have a required field. When I am in the cell, it correctly appears with a red border as shown in the attached screen shot. If I move out of the cell, the red border goes away. So it no longer shows where the error is located.

Any idea what could be wrong? (I am using similar code to that you provided except the icon.)
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 04:56 PM
Hi Deborah, 

If you breakpoint in CellFormatting event, does it hit the 
If cell.ContainsErrors Then
...
My guess is that there is a problem in the validation that is not seeing this as empty.
you could of course also add
if cell.ContainsErrors or String.IsNullOrEmpty(cell.Text.Trim()) then
...
End If

Let me know if that helps
Richard
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 05:00 PM
Hi again Deborah, 

I may be wrong, but from your screenshot it looks like you are creating a reminder system. Just a suggestion, but if that's the case, perhaps the RadReminder and RadScheduler would be best suited to this. 
Richard
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 05:04 PM
By the way Deborah, can you confirm which version of the RadControls you are currently using? 
Thanks
Richard
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 05:13 PM
Yes, it is hitting that code, which is why it is turning red when in the cell. I just don't understand why it does not stay red. Is the theme overriding it? (We are using the Office theme.)

No I cannot add the IsNullOrEmpty code as you suggested because based on other issues with the grid, we are inheriting from your grid and building our own. We have grids on many, many forms and want to minimize the amount of repeated code in each form.

All of our business objects implement IDataErrorInfo, which is what defines the error and the error text. Not every cell is required. Only those defined by the business object to be required.

Do you know if Telerik has fully tested the error handling with business objects that implement IDataErrorInfo? Do you know if they have an example somewhere that demonstrates how they do it?

Thanks!
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 05:16 PM
No, we are creating a proprietary application that will be sold as a product where one dialog of the many, many dialogs adds reminders for the application. So even though this is the one I provided as an example, this problem needs to be resolved for *all* of our grids.
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 05:22 PM
Could you post your class that implements IDataErrorInfo in the meantime please Deborah? 
Thanks
0
Emanuel Varga
Top achievements
Rank 1
answered on 19 Oct 2010, 05:27 PM
Hello,

Richard is right on this one, CellFormatting is the way to go on this one, in my opinion.

Second, the Grid should / is using the IDataErrorInfo to check for errors in the cell, i read about this somewhere, but i didn't have time to test it yet, but it should work as expected (except that error image that will not show up in the cell)

Best Regards,
Emanuel Varga
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 05:30 PM

This is a very complex application with a "full blown" framework. So I don't have a simple example to post.

All of the business objects inherit from a business object base class. The business object base class is a more complex version of what I shared publically here:

http://msmvps.com/blogs/deborahk/archive/2009/07/21/building-a-business-object-base-class.aspx

The individual business object classes then just call the validation methods in the property setters, like this:

Private _ReminderText As String
''' <summary>
''' Gets or sets Reminder Text
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property ReminderText() As String
    Get
        Return _ReminderText
    End Get
    Set(ByVal value As String)
        If _ReminderText Is Nothing OrElse _
                Not _ReminderText.Equals(value) Then
            Dim propertyName As String = "ReminderText"
            ' Validation
            Me.ValidationInstance.ValidateClear(propertyName)
            Me.ValidationInstance.ValidateRequired(propertyName, value)
            ' Set the value
            If _ReminderText IsNot Nothing OrElse value IsNot Nothing Then
                _ReminderText = value
                SetEntityState(EntityStateType.Modified, propertyName)
            End If
        End If
    End Set
End Property


Is it possible that the theme is interfering with the display?

0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 05:35 PM
It is definitely *not* the business objects because the error icons are displayed. See the attached screen shots.

So there are two problems:
1) Even though I tell the icon to align MiddleRight, it is appearing in the center of the control and not on the right.
2) The red highlighting only appears when the user is in the cell.

Any tips for fixing these items?
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 05:36 PM
I believe it is the most recent version, but is there an easy way to tell?

I opened the about box, but was surprised to see no version information in it.
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 05:37 PM
Hi Deborah, 

Here is a very simple test. A grid which is bound to a collection of objects that implement the interface. The class always ensures that an error is thrown for the "Name" cell. 

Imports Telerik.WinControls
Imports Telerik.WinControls.UI
Imports System.Collections.ObjectModel
Imports System.Collections.Generic
Imports System.Collections
Imports System.ComponentModel
 
 
Public Class Form1
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            Dim somethings As New Somethings()
            Me.RadGridView1.DataSource = New BindingList(Of Something)(somethings.GetSomethings())
            CType(Me.RadGridView1.Columns(0), GridViewDataColumn).SortOrder = RadSortOrder.Descending
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub
 
 
    Private Sub RadGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As Telerik.WinControls.UI.CellFormattingEventArgs) Handles RadGridView1.CellFormatting
        Dim cell As GridDataCellElement = TryCast(e.CellElement, GridDataCellElement)
        If cell IsNot Nothing Then
            If cell.ContainsErrors Then
                cell.DrawBorder = True
                cell.BorderBoxStyle = BorderBoxStyle.SingleBorder
                cell.BorderWidth = 2
                cell.BorderColor = Color.Red
                cell.Image = My.Resources._error
                cell.TextImageRelation = TextImageRelation.ImageBeforeText
                cell.ImageAlignment = ContentAlignment.MiddleRight
            Else
                cell.ResetValue(LightVisualElement.DrawBorderProperty, ValueResetFlags.Local)
                cell.ResetValue(LightVisualElement.BorderBoxStyleProperty, ValueResetFlags.Local)
                cell.ResetValue(LightVisualElement.BorderWidthProperty, ValueResetFlags.Local)
                cell.ResetValue(LightVisualElement.BorderColorProperty, ValueResetFlags.Local)
            End If
        End If
 
    End Sub
End Class
 
Public Class Somethings
 
    Public Sub New()
    End Sub
 
    Public Function GetSomethings() As System.Collections.Generic.List(Of Something)
        Dim somethingList As New System.Collections.Generic.List(Of Something)
        somethingList.Add(New Something("Name1", "Description1"))
        somethingList.Add(New Something("Name2", "Description2"))
        somethingList.Add(New Something("Name3", "Description3"))
        somethingList.Add(New Something("Name4", "Description4"))
        Return somethingList
    End Function
End Class
 
Public Class Something
    Implements IDataErrorInfo
 
    Private m_Name As String
    Private m_Description As String
 
    Public Sub New()
    End Sub
 
    Public Sub New(ByVal name As String, ByVal description As String)
        m_Name = name
        m_Description = description
    End Sub
 
    Public Property Name() As String
        Get
            Return m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
 
    Public Property Description() As String
        Get
            Return m_Description
        End Get
        Set(ByVal value As String)
            m_Description = value
        End Set
    End Property
 
    Public ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.Error
        Get
            If False = False Then
                Return "Invalid"
            Else
                Return String.Empty
            End If
        End Get
    End Property
 
    Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
        Get
            If columnName = "Name" And False = False Then
                Return "Not a valid value"
            Else
                Return String.Empty
            End If
        End Get
    End Property
End Class

See attached screenshot
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 05:44 PM
Just tried changing the theme of the Grid to Office2007Silver and there was no change. 
Richard
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 05:48 PM
For the version, have a look at one of your Telerik DLL references. 
Thanks
Richard
0
Emanuel Varga
Top achievements
Rank 1
answered on 19 Oct 2010, 05:54 PM
I would also suggest checking for some additional formatting that may cancel out the borders. Please try setting the background of the cell to a different color, and if that remains the same even after you change the row, something else is causing a reset of the border property.

Best Regards,
Emanuel Varga
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 07:04 PM
2010.2.10.806

Is that the most recent?

Because even with your code changes, I still see the icon in the middle of the cell as per my screen shots.
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 07:05 PM
Is this correct? That I have to set the ImageAlignment twice?

cell.Image = My.Resources._error
cell.ImageAlignment = ContentAlignment.BottomLeft
cell.TextImageRelation = TextImageRelation.ImageBeforeText
cell.ImageAlignment = ContentAlignment.MiddleRight
0
Emanuel Varga
Top achievements
Rank 1
answered on 19 Oct 2010, 07:07 PM
Hello Deborah,

No, this is the SP1 version, the most current one is 914, SP2 version, i would suggest updating to the new version.

And remove one of that assignations, the first one is useless if you change if afterwards.

Best Regards,
Emanuel Varga
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 07:27 PM
Hi Deborah,

No, this is just my enthusiastic typing and forgot to remove one of the assignments. You just need the one.
Best wishes
Richard
0
Accepted
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 08:15 PM
Hi again Deborah,

Here is a fully working example with validation on the object and the ShowRowHeaderColumn set to false.
It will ensure that 'Name' cannot be Name and 'Name' cannot be empty.

It shows a red border around the cells with the error and an image in the cell as you do not have ShowRowHeaderColumn set to true.

I hope this helps
Richard
Imports Telerik.WinControls
Imports Telerik.WinControls.UI
Imports System.Collections.ObjectModel
Imports System.Collections.Generic
Imports System.Collections
Imports System.ComponentModel
  
  
Public Class Form1
  
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            Me.RadGridView1.ShowRowHeaderColumn = False
            Dim somethings As New Somethings()
            Me.RadGridView1.DataSource = New BindingList(Of Something)(somethings.GetSomethings())
            CType(Me.RadGridView1.Columns(0), GridViewDataColumn).SortOrder = RadSortOrder.Descending
            Me.RadGridView1.MasterTemplate.BestFitColumns()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub
  
  
    Private Sub RadGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As Telerik.WinControls.UI.CellFormattingEventArgs) Handles RadGridView1.CellFormatting
        Dim cell As GridDataCellElement = TryCast(e.CellElement, GridDataCellElement)
        If cell IsNot Nothing Then
            If cell.ContainsErrors Then
                cell.DrawBorder = True
                cell.BorderBoxStyle = BorderBoxStyle.SingleBorder
                cell.BorderWidth = 2
                cell.BorderColor = Color.Red
                cell.Image = My.Resources._error
                cell.ImageAlignment = ContentAlignment.MiddleLeft
                cell.TextImageRelation = TextImageRelation.ImageBeforeText
            Else
                cell.ResetValue(LightVisualElement.DrawBorderProperty, ValueResetFlags.Local)
                cell.ResetValue(LightVisualElement.BorderBoxStyleProperty, ValueResetFlags.Local)
                cell.ResetValue(LightVisualElement.BorderWidthProperty, ValueResetFlags.Local)
                cell.ResetValue(LightVisualElement.BorderColorProperty, ValueResetFlags.Local)
                cell.Image = Nothing
            End If
        End If
  
    End Sub
End Class
  
Public Class Somethings
  
    Public Sub New()
    End Sub
  
    Public Function GetSomethings() As System.Collections.Generic.List(Of Something)
        Dim somethingList As New System.Collections.Generic.List(Of Something)
        somethingList.Add(New Something("Name1", "Description1"))
        somethingList.Add(New Something("Name2", "Description2"))
        somethingList.Add(New Something("Name3", "Description3"))
        somethingList.Add(New Something("Name4", "Description4"))
        Return somethingList
    End Function
End Class
  
Public Class Something
    Implements IDataErrorInfo
  
    Private m_Name As String
    Private m_Description As String
  
    Public Sub New()
    End Sub
  
    Public Sub New(ByVal name As String, ByVal description As String)
        m_Name = name
        m_Description = description
    End Sub
  
    Public Property Name() As String
        Get
            Return m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
  
    Public Property Description() As String
        Get
            Return m_Description
        End Get
        Set(ByVal value As String)
            m_Description = value
        End Set
    End Property
  
    Public ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.Error
        Get
            If Not IsNameValid() Then
                Return "Cannot be 'Name' or Empty"
            Else
                Return ""
            End If
        End Get
    End Property
  
    Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
        Get
            If columnName = "Name" AndAlso Not IsNameValid() Then
                Return "Not a valid value"
            Else
                Return ""
            End If
        End Get
    End Property
  
    Private Function IsNameValid() As Boolean
        If String.IsNullOrEmpty(Me.Name) Then
            Return False
        End If
        If String.Equals(Me.Name.ToUpperInvariant(), "NAME") Then
            Return False
        End If
        Return True
    End Function
End Class
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 08:20 PM
And an example screenshot after I've loaded the grid (which is Office2007 themed) and added two invalid rows. One with Name and one with empty data.
Richard
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 08:58 PM
I just looked at your screen shot and noticed that you were not able to get the icon to appear to the right either.

If there is no text, it appears in the center both in your example and mine.

So there is no way to set the icon to be at the right of the cell?
0
Accepted
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 09:10 PM
Hi Deborah,

i know it's not ideal, but whilst I look at another way you could replace the CellFormatting event with this one.

Private Sub RadGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As Telerik.WinControls.UI.CellFormattingEventArgs) Handles RadGridView1.CellFormatting
    Dim cell As GridDataCellElement = TryCast(e.CellElement, GridDataCellElement)
    If cell IsNot Nothing Then
        If cell.ContainsErrors Then
            cell.DrawBorder = True
            cell.BorderBoxStyle = BorderBoxStyle.SingleBorder
            cell.BorderWidth = 2
            cell.BorderColor = Color.Red
            cell.Image = My.Resources._error
            If String.IsNullOrEmpty(cell.Text) Then cell.Text = " "
            cell.ImageAlignment = ContentAlignment.MiddleRight
            cell.TextImageRelation = TextImageRelation.TextBeforeImage
        Else
            cell.ResetValue(LightVisualElement.DrawBorderProperty, ValueResetFlags.Local)
            cell.ResetValue(LightVisualElement.BorderBoxStyleProperty, ValueResetFlags.Local)
            cell.ResetValue(LightVisualElement.BorderWidthProperty, ValueResetFlags.Local)
            cell.ResetValue(LightVisualElement.BorderColorProperty, ValueResetFlags.Local)
            cell.Image = Nothing
        End If
    End If
End Sub
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 09:13 PM
And the screenshot
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 09:27 PM
OK, faking some text in did the trick for getting the icon to appear to the right. I assume that is a "bug" that you can submit for correction?

I still cannot get the borders to stay on. I tried starting with a new project and using your code, and the borders did stay on. So I assume that it is something more specific to my grid. I'll keep trying.

Thanks for your help!
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 09:31 PM
Hi Deborah,

Really glad that worked for you. I'd suggest you submit a feature request to enable a "DisplayStyle" such as other controls have perhaps, (other controls have a DisplayStyle with an Enum of ImageAndText, None, Text, Image) - though I can see why that may not be suitable for the grid cells.
I'm afraid I can't submit anything for correction as I'm just another user of the controls like yourself, but glad to have been able to help.
All the best
Richard
0
Deborah
Top achievements
Rank 1
answered on 19 Oct 2010, 09:33 PM
OK, I got it to work.

I was trying some other things at one point and had removed the line that set the BorderBoxStyle. When I recompared your code to mine, I realized that it was missing and added it back. It now works!

Thanks!
0
Richard Slade
Top achievements
Rank 2
answered on 19 Oct 2010, 09:38 PM
Excellent!
Enjoy the rest of your day.
Richard
0
Allen
Top achievements
Rank 1
answered on 21 Dec 2010, 09:43 AM
Hi, Deborah,
@"OK, faking some text in did the trick for getting the icon to appear to the right. I assume that is a "bug" that you can submit for correction?"

I read another post and got the solution , hope it helps:


GridDataCellElement cell = e.CellElement 
as GridDataCellElement;
if (cell != null)
{
    if (cell.ContainsErrors)
    {
        //cell.Image = ;
        cell.TextImageRelation = TextImageRelation.TextBeforeImage;
        cell.ImageAlignment = ContentAlignment.MiddleRight;
        cell.ImageLayout = ImageLayout.None;//The missing one
    }
    else
    {
        cell.Image = null;
    }
}

Allen
Tags
GridView
Asked by
Deborah
Top achievements
Rank 1
Answers by
Richard Slade
Top achievements
Rank 2
Deborah
Top achievements
Rank 1
Emanuel Varga
Top achievements
Rank 1
Allen
Top achievements
Rank 1
Share this question
or