WinForms/.NETFramework: форматирование DataGridViewCell в соответствии с ValidationResultC#

Место общения программистов C#
Anonymous
WinForms/.NETFramework: форматирование DataGridViewCell в соответствии с ValidationResult

Сообщение Anonymous »

Рассмотрим небольшое приложение Winforms, в котором есть список пользовательских объектов, привязанных к DataGridView.
Класс данных:

Код: Выделить всё

public class MyAwesomeClass : IDataErrorInfo, INotifyPropertyChanged
{
string _Name;
public string Name { get { return _Name; } set { if(Name is null || !Name.Equals(value)) { _Name = value; Changed(nameof(Name)); } } }

int _MyVal;

[CustomValidation(typeof(MyAwesomeValidator), nameof(MyAwesomeValidator.ValidateIntVal))]
public int MyVal { get { return _MyVal; } set { if(!MyVal.Equals(value)) { _MyVal = value; Changed(nameof(MyVal)); } } }

private void Changed(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}

//Nicked from: https://reza-aghaei.com/dataannotations-validation-attributes-in-windows-forms/
[Browsable(false)]
public string this[string property]
{
get
{
var propertyDescriptor = TypeDescriptor.GetProperties(this)[property];
if (propertyDescriptor == null)
return string.Empty;

var results = new List();
var result = Validator.TryValidateProperty(
propertyDescriptor.GetValue(this),
new ValidationContext(this, null, null)
{ MemberName = property },
results);
if (!result)
return results.First().ErrorMessage;
return string.Empty;
}
}

[Browsable(false)]
public string Error
{
get
{
var results = new List();
var result = Validator.TryValidateObject(this,
new ValidationContext(this, null, null), results, true);
if (!result)
return string.Join(Environment.NewLine, results.Select(x => x.ErrorMessage));
else
return null;
}
}

public static IEnumerable DummyData
{
get { return new [] { new MyAwesomeClass("a", -2),
new MyAwesomeClass("b", 3),
new MyAwesomeClass("c", 8)
};
}
}
}
Пользовательский класс ValidationResult:

Код: Выделить всё

public class CustomValidationResult : ValidationResult
{
public enum ResultState { Warning, Error }

public ResultState State { get; private set; }

public CustomValidationResult(string errorMessage, ResultState state) : base(errorMessage)
{
ResultState = state;
}

public static ValidationResult Success
{
get { return ValidationResult.Success; }
}
}
Валидатор:

Код: Выделить всё

public class MyAwesomeValidator
{
public static ValidationResult ValidateIntVal(int value, ValidationContext Context)
{
if (value < 0)
return new CustomValidationResult("The value cannot be smaller than 0", CustomValidationResult.ResultState.Error);

if (value <  5)
return new CustomValidationResult("The value is a bit small, isn't it?", CustomValidationResult.ResultState.Warning);

return CustomValidationResult.Success;
}
}
Класс, отвечающий за стилизацию ячеек с ошибками:

Код: Выделить всё

   class DataGridViewCellFormatter
{
DataGridView Dgv;

public DataGridViewCellFormatter(DataGridView dgv)
{
Dgv = dgv;
Dgv.CellFormatting += Dgv_CellFormatting;
}

private void Dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewCell cell = Dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];

if (!string.IsNullOrWhiteSpace(cell.ErrorText))
{
cell.Style.BackColor = Color.Red;
}
else
{
cell.Style.BackColor = cell.OwningColumn.DefaultCellStyle.BackColor;
}
}
}
Форма (отрывок):

Код: Выделить всё

public partial class frm_DemoForm : Form
{
BindingList Data;
DataGridViewCellFormatter coloring;

public frm_DemoForm()
{
Data = new BindingList(MyAwesomeClass.DummyData.ToList());

InitializeComponent();

coloring = new DataGridViewCellFormatter(dataGridView1);

dataGridView1.DataSource = Data;
}
}
Теперь, если я все написал правильно, DataGridView должен отображать 3 строки (a, b и c) и показывать ошибки в первых двух (первое значение ниже нуля и, следовательно, ошибка, а второе находится в диапазоне «все еще немного мало» и, следовательно, предупреждение). DataGridViewCellFormatter проверит ErrorText каждой ячейки и раскрасит ячейку соответствующим образом.
НО
Эта форма проверки допускает только двоичное форматирование: ошибка или отсутствие ошибки. Если я хочу окрасить ячейку в оранжевый цвет, если это всего лишь предупреждение, мне нужно добавить к тексту ошибки префикс или суффикс «

Код: Выделить всё

[Warning]" и "[Error]
" (что я, вероятно, могу пропустить и принять все, что не имеет префикса, как ошибку), чтобы иметь возможность уловить различия в серьезности.
НО
Поскольку у меня уже есть такой хороший CustomValidationResult, который обеспечивает нужную мне степень детализации через свойство State, мне было интересно, есть ли способ элегантно подключить DataGridView к фактическому Объект(ы) ValidationResult и воздействуйте на них, а не на ErrorText каждой ячейки, которую я не хочу рассылать спамом с помощью "

Код: Выделить всё

[Warning]
" токен.

Вернуться в «C#»