Search code examples
c#wpfvalidationwpfdatagridwpftoolkit

Validation in a datagrid accessing the View Model?


I've been looking into this issue for almost 3 days now. Searches have turned up nothing yet. The questions look like they would answer my question but ends up being something totally different. So here goes:

I have a view that is tied to a view model. In the view I have a DataGrid which is populated by a list in the view model. Our standard is to have data error validation occur where the field will be highlighted in red and the tooltip contains the error message. From what I've read to do that in a DataGrid I need to perform validation in the class definition at the property level.

The validation is looking to see if the value entered is already existing in the list of items in the DataGrid which is help in the View Model. I cannot figure out how to get addressability to the view model from my class definition.

My resource dictionary definitions:

<Style x:Key="DataGridTextBlockStyle" TargetType="{x:Type TextBlock}">
 <Style.Triggers>
  <Trigger Property="Validation.HasError" Value="true">
   <Setter Property="ToolTip"
      Value="{Binding RelativeSource={RelativeSource Self},
      Path=(Validation.Errors)[0].ErrorContent}"/>
   <Setter Property="ToolTipService.ShowDuration"
             Value="20000"/>
  </Trigger>
</Style.Triggers>

My datagrid definition:

        <wpftk:DataGrid x:Name="SegmentGrid"
          IsEnabled="True"      
          AutoGenerateColumns="False" 
          VerticalScrollBarVisibility="Auto" 
          Height="90" 
          ItemsSource="{Binding SegmentList}" 
          CanUserAddRows="False" CanUserDeleteRows="False" >
          <event:EventCommandBehavior.EventCommands>
              <event:EventCommand 
                 RoutedEvent="wpftk:DataGrid.SelectionChanged" 
                   Command="{Binding RegionSelectionChanged}"/>
              </event:EventCommandBehavior.EventCommands>
              <wpftk:DataGrid.Columns>
                  <wpftk:DataGridTextColumn Header="Name" 
                       Width="265" 
                       Binding="{Binding RegionName}" />
                                  <!--  The Priority Column -->
            <wpftk:DataGridTemplateColumn Header="Priority" Width="80">
              <wpftk:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <TextBlock Style="{StaticResource DataGridTextBlockStyle}" 
                         Text="{Binding Priority, Mode=TwoWay,  
                           ValidatesOnDataErrors=True, 
                           ValidatesOnExceptions=True,
                           UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
              </wpftk:DataGridTemplateColumn.CellTemplate>
              <wpftk:DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                  <TextBox>
                    <TextBox.Text>
                      <Binding Path="Priority"  
                           UpdateSourceTrigger="PropertyChanged" 
                           ValidatesOnDataErrors="True" 
                           ValidatesOnExceptions="True">
                      </Binding>
                    </TextBox.Text>
                    <TextBox.Style>
                      <Style TargetType="TextBox" BasedOn="{StaticResource CellEditStyle}" />
                    </TextBox.Style>
                  </TextBox>
                </DataTemplate>
              </wpftk:DataGridTemplateColumn.CellEditingTemplate>
            </wpftk:DataGridTemplateColumn>
                  <wpftk:DataGridCheckBoxColumn Header="Write To Cartridge"
                       Binding="{Binding WriteToCartridge, Mode=TwoWay}"/>
              </wpftk:DataGrid.Columns>
      </wpftk:DataGrid>
    </StackPanel>

The Priority field is the only one being validated but I'm having a bugger of a time getting it validated. Everything I've found (doing validation in the Priority setter, doing validation in a custom validator class) all do standalone validation that has no access to the DataContext object.

Does anyone know of a way to either gain access to the DataContext or point to a method in my class to do the validation inside it? I tried inheriting the IDataErrorInfo interface in my DataContext class but that did not ever get called by the DataGrid cell.


Solution

  • Well it took a bit to get things working but here is what I implemented:

    In the data object, I implemented INotifyPropertyChanged and when the Priority field is changed I notify the listeners of the change.

    In the view model: I implemented the logic to set the listener for the PropertyChanged event and if the value already exists in the list of regions, I set a Boolean in the object indicating it is in a duplicate state.

    Finally in the data object I implemented the IDataErrorInfo interface and if the propertyName is Priority and the Boolean is true then I return my custom error.

    Worked first time once all the pipe was in place!