Hello,
I have two issues.
The first issue is that I'm binding a Model to RadGridView, and throwing an exception when a value is invalid, and when throwing an exception from a property and catching it with DataError, GridViewDataErrorEventArgs.Exception is not the exception that was thrown from the property, but I get Object of type 'System.DBNull' cannot be converted to type 'System.String'.
This only happens when the property is null or empty string.
FYI, I'm allowing incorrect values to be assigned and do the validation after assigning the value to the property, and this is what I want, because I want to give the user an opportunity to correct base on the original value they entered.
Another issue is that when drawing borders to indicate which cell has a problem, not all borders appear.
As you can see above, I'm missing the top border.
It happens to another theme and sometimes the right side border is missing.
How can I make it so that all the borders appear?
The below is the sample code that you can use to reproduce the errors.
To reproduce the first problem, edit the first cell, clear the value, and the property will throw a "Please enter category name." exception but the exception in RadGridView1_DataError is Object of type 'System.DBNull' cannot be converted to type 'System.String' not the exception thrwon from the property setter.
To reproduce the second problem, edit the first cell, enter any value that is longer than 5 characters and you will see the red border without the top border.
public partial class GridViewTestForm : Form
{
public GridViewTestForm()
{
InitializeComponent();
List<GridViewDataColumn> gridColumns = new List<GridViewDataColumn>();
gridColumns.Add(new GridViewTextBoxColumn
{
DataType = typeof(string),
TextAlignment = ContentAlignment.MiddleLeft,
FieldName = nameof(ReportCategoryViewModel.CategoryName),
HeaderText = "Category Name",
AutoSizeMode = BestFitColumnMode.DisplayedCells,
});
gridColumns.Add(new GridViewTextBoxColumn
{
DataType = typeof(string),
TextAlignment = ContentAlignment.MiddleLeft,
FieldName = nameof(ReportCategoryViewModel.NumberOfReportsUsingCategory),
HeaderText = "# Reports",
ReadOnly = true,
AutoSizeMode = BestFitColumnMode.DisplayedCells,
});
gridColumns.Add(new GridViewTextBoxColumn
{
DataType = typeof(string),
TextAlignment = ContentAlignment.MiddleLeft,
FieldName = nameof(ReportCategoryViewModel.Description),
HeaderText = "Description",
});
// Add the columns to the grid
radGridView1.MasterTemplate.Columns.AddRange(gridColumns);
radGridView1.EnableSorting = true;
radGridView1.MasterTemplate.AllowMultiColumnSorting = true;
radGridView1.DataError += RadGridView1_DataError;
radGridView1.CellValidating += RadGridView1_CellValidating;
var viewModel = new ReportCategoryManagementViewModel();
viewModel.LoadReportCategories();
radGridView1.DataSource = viewModel.ReportCategories;
}
private void RadGridView1_CellValidating(object sender, CellValidatingEventArgs e)
{
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = string.Empty;
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.CustomizeBorder = false;
}
private void RadGridView1_DataError(object sender, GridViewDataErrorEventArgs e)
{
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = e.Exception.Message;
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.CustomizeBorder = true;
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.DrawBorder = true;
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BorderWidth = 1;
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BorderGradientStyle = Telerik.WinControls.GradientStyles.Solid;
radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BorderColor = Color.Red;
e.Cancel = true;
}
}
public class NotifyPropertyBase : INotifyPropertyChanged
{
public bool IgnoreValidation { get; set; } = false;
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChangedRaised([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class ReportCategoryManagementViewModel : NotifyPropertyBase
{
private ObservableCollection<ReportCategoryViewModel> _reportCategories = null;
public ObservableCollection<ReportCategoryViewModel> ReportCategories => _reportCategories;
public event EventHandler<List<ReportCategoryViewModel>> ReportCategoriesLoaded;
public bool _isBusy = false;
public bool IsBusy { get => _isBusy; set { if (_isBusy != value) { _isBusy = value; OnPropertyChangedRaised(); } } }
public ReportCategoryManagementViewModel()
{
}
public void LoadReportCategories()
{
_reportCategories = new ObservableCollection<ReportCategoryViewModel>()
{
new ReportCategoryViewModel()
{
IgnoreValidation = true,
CategoryName = "My category",
NumberOfReportsUsingCategory = 2,
Description = "my optional description for my category"
}
};
foreach(var category in _reportCategories)
category.IgnoreValidation = false;
}
}
public class ReportCategoryViewModel : NotifyPropertyBase
{
public EntityState State { get; private set; } = EntityState.Unchanged;
private string _categoryName = string.Empty;
public string CategoryName
{
get => _categoryName;
set
{
if (_categoryName != value)
{
_categoryName = value;
OnPropertyChangedRaised();
if (!IgnoreValidation)
{
if (!string.IsNullOrWhiteSpace(_categoryName))
{
if (_categoryName.Length > 5)
throw new Exception("Maximum character is 5.");
}
else
{
_categoryName = string.Empty;
throw new Exception("Please enter category name.");
}
}
}
}
}
private int _numberOfReportsUsingCategory;
public int NumberOfReportsUsingCategory { get => _numberOfReportsUsingCategory; set { if (_numberOfReportsUsingCategory != value) { _numberOfReportsUsingCategory = value; OnPropertyChangedRaised(); } } }
private string _description;
public string Description { get => _description; set { if (_description != value) { _description = value; OnPropertyChangedRaised(); } } }
}