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

Validation error in custom column with multiple controls

6 Answers 99 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Terry Foster
Top achievements
Rank 1
Terry Foster asked on 06 Jun 2011, 07:13 PM
I've created a custom column that derives from GridViewBoundColumnBase that has a TextBlock and a RadComboBox as the cell edit elements.  The TextBlock is bound to a property on my view model which implements the INotifyDataErrorInfo interface.  When the user enters an invalid valid, the TextBlock highlights red with an error tip as expected, but the user can end editing for the cell, keeping the invalid value.  This is in direct contrast to the default behavior of the GridViewDataColumn which does not allow the user to end editing until they fix the error or press the 'Esc' key.  How can I get this same behavior for my custom column?

Thanks,
Terry

6 Answers, 1 is accepted

Sort by
0
Terry Foster
Top achievements
Rank 1
answered on 08 Jun 2011, 07:21 PM

Here's a slightly simplified version of my class:

 

 

 

 

public sealed class GridViewTimeLengthColumn : GridViewBoundColumnBase

 

 

{

 

 

 

public bool TimeUnitEnabled { get; set; }

 

 

 

 

public override string UniqueName

 

 

{

 

 

 

get { return base.UniqueName; }

 

 

 

 

set

 

 

{

 

 

 

base.UniqueName = value;

 

 

DataMemberBinding.Path =

 

new PropertyPath(value + "Summary"); // for sort/filter/group

 

 

}

 

}

 

 

 

public GridViewTimeLengthColumn()

 

 

{

 

TimeUnitEnabled =

 

true;

 

 

}

 

 

 

public override FrameworkElement CreateCellElement(GridViewCell cell, object dataItem)

 

 

{

 

 

 

return new TextBlock().SetOneWayBinding(TextBlock.TextProperty, UniqueName + "Summary");

 

 

}

 

 

 

public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)

 

 

{

 

 

 

var grid = new Grid();

 

 

grid.ColumnDefinitions.Add(

 

new ColumnDefinition());

 

 

grid.ColumnDefinitions.Add(

 

new ColumnDefinition() { Width = GridLength.Auto });

 

 

 

 

var textBox = new TextBox().SetTwoWayBinding(TextBox.TextProperty, UniqueName);

 

 

grid.Children.Add(textBox);

 

 

 

var comboBox = new RadComboBox()

 

 

.SetOneWayBinding(

 

RadComboBox.ItemsSourceProperty, UniqueName + "TimeUnitItemsSource")

 

 

.SetTwoWayBinding(

 

RadComboBox.SelectedItemProperty, UniqueName + "TimeUnit");

 

 

 

 

Grid.SetColumn(comboBox, 1);

 

 

comboBox.IsEnabled = TimeUnitEnabled;

 

grid.Children.Add(comboBox);

 

 

 

return grid;

 

 

}

 

}

 


The 'SetOneWayBinding' and 'SetTwoWayBinding' methods are just extension methods that establish the bindings and set validation-related binding properties to 'true', all in one convenient call.  As we're quickly approaching a deadline, any timely help you could provide on this would be greatly appreciated.

Thanks,
Terry

0
Maya
Telerik team
answered on 09 Jun 2011, 01:18 PM
Hi Terry Foster,

Generally, you may skip setting the validation-related properties of the binding. As once you set them, the Framework will perform the validation. What you may try to do is to handle the CellValidating event of the grid and perform the logic there.
 

Kind regards,
Maya
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Terry Foster
Top achievements
Rank 1
answered on 09 Jun 2011, 02:06 PM
Hi Maya,

I don't think I'm understanding.  I definitely don't want to handle the CellValidating event of the grid as I'm dong everything MVVM-style.  That is why I'm setting the NotifyOnValidationError and ValidatesOnExceptions properties of the bindings to true.  I'm not sure why you say I can generally skip setting these, as validation through the binding of my view model's properties would no longer work.

Ultimately, I just need to know exactly what prevents the cell from ending editing when one of the bindings has a validation error (as managed through the INotifyDataErrorInfo interface implemented by the view model) so I can do the same for this custom column.

Thanks,
Terry
0
Maya
Telerik team
answered on 09 Jun 2011, 03:52 PM
Hello Terry Foster,

Basically, for the time being the way to go is to handle the CellValidated event and perform the validation logic there. If you do not want to write any code in your code-behind, you might try to create a custom attached behavior and define it for the RadGridView.
On the other hand, we will do consider adding a method allowing the implementation of custom validation logic. However, I cannot specify any time frame for including such a feature.
 

Regards,
Maya
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Luis Takada
Top achievements
Rank 1
answered on 24 Aug 2011, 10:05 PM
Hi Maya, as I was searching for a solution to my problem I came across this issue that is somewhat similar to what I have.
I have a custom cell created in CreateCellEditElement() that is a grid with a textBox and a comboBox. I added the binding and a converter to it. The controls work fine but when I edit the textBox, it fires CellValidating event and there the new value in e.NewValue member is coming as null instead of the edited value.

private void _grid_CellValidating(object sender, GridViewCellValidatingEventArgs e)
{
    List<object> values = e.Row.Item as List<object>;
    if (values != null)
    {
        int index = e.Row.Cells.IndexOf(e.Cell);
 
        ScenarioValue value = values[index] as ScenarioValue;
        if (value != null)
        {
            string errorDescription = "";
            e.IsValid = value.IsValid(e.NewValue as string, out errorDescription);
            e.ErrorMessage = errorDescription;
            e.Handled = true;
        }
        else
        {
            Parameter parameter = values[index] as Parameter;
            if (parameter != null)
            {
                string errorDescription = "";
                e.IsValid = parameter.IsValid(e.NewValue as string, out errorDescription);
                e.ErrorMessage = errorDescription;
                e.Handled = true;
            }
        }
    }
}
 
 
public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)
{
    List<object> row = dataItem as List<object>;
 
    if (parameter.ParameterType == ParameterType.Time)
    {
        var grid = new Grid();
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
 
        Binding gridBinding = new Binding(DataMemberBinding.Path.Path);
        gridBinding.Mode = BindingMode.TwoWay;
        gridBinding.NotifyOnValidationError = true;
        gridBinding.ValidatesOnExceptions = true;
        gridBinding.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
        gridBinding.Converter = new TimeAndUnitConverter(TimeAndUnitConverter.DataPortion.Time);
        grid.SetBinding(TextBox.TextProperty, gridBinding);
 
 
        var textBox = new TextBox();
        Binding bindingTextBox = new Binding(DataMemberBinding.Path.Path);
        bindingTextBox.Mode = BindingMode.TwoWay;
        bindingTextBox.NotifyOnValidationError = true;
        bindingTextBox.ValidatesOnExceptions = true;
        bindingTextBox.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
        bindingTextBox.Converter = new TimeAndUnitConverter(TimeAndUnitConverter.DataPortion.Time);
        textBox.SetBinding(TextBox.TextProperty, bindingTextBox);
        textBox.Height = 22;
        grid.Children.Add(textBox);
 
        var comboBox = new RadComboBox();
        comboBox.ItemsSource = Parameter.TimeUnits;
 
        Binding bindingCombo = new Binding(DataMemberBinding.Path.Path);
        bindingCombo.Mode = BindingMode.TwoWay;
        bindingCombo.NotifyOnValidationError = true;
        bindingCombo.ValidatesOnExceptions = true;
        bindingCombo.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
        bindingCombo.Converter = new TimeAndUnitConverter(TimeAndUnitConverter.DataPortion.Unit);
        comboBox.SetBinding(RadComboBox.SelectedItemProperty, bindingCombo);
        Grid.SetColumn(comboBox, 1);
        comboBox.IsEnabled = true;
        grid.Children.Add(comboBox);
 
        return grid;
    }
    else
    {
        return base.CreateCellEditElement(cell, dataItem);
    }
}
0
Maya
Telerik team
answered on 29 Aug 2011, 03:07 PM
Hi Luis Takada,

This would be the expected behavior since you predefine the editing element of the cell. What you may try is to override the GetNewValueFromEditor(object editor) method in the column definition and return the value you want. Another possible approach would be to find the TextBox/ RadComboBox from the EditingElement property of the arguments of the CellValidating event and get their values.
 

Best wishes,
Maya
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

Tags
GridView
Asked by
Terry Foster
Top achievements
Rank 1
Answers by
Terry Foster
Top achievements
Rank 1
Maya
Telerik team
Luis Takada
Top achievements
Rank 1
Share this question
or