R. Wood
R. Wood

Reputation: 101

Bind row instead of cell to converter when using C# WPF DataGrid DataGridTemplateColumn

I have a datagrid of which the ItemsSource is set dynamically and I'm using DataGridTemplateColumns to determine available dropdown options as well as displaying validation. In the case of validation I am colouring the cell background red to be obvious to a user. I am using a converter to do this like so:

public class ExampleForSOBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string input = value as string;
        switch (input)
        {
            case "0":
            case "":
            case null:
                return Brushes.Red;                    
            default:
                return DependencyProperty.UnsetValue;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

And the style code looks like this:

<DataGridTemplateColumn.CellStyle>
                                    <Style TargetType="{x:Type DataGridCell}">
                                        <Setter Property="Background" Value="{Binding NameOfColumnInDataRow, Converter={StaticResource ExampleForSOBrushConverter}}"/>
                                    </Style>
                                </DataGridTemplateColumn.CellStyle>

All this is doing is checking if the value entered on the cell is blank, empty or contains 0 (a default dropdown option for not selected). So far this is working great, however, I now need to apply validation on some columns based on others or via different checks such as text length. For example if ColumnB is 1 and ColumnC is 3, or if ColumnD is less than 8 characters.

My plan was to use parameters and pass the row like this:

<DataGridTemplateColumn.CellStyle>
                                    <Style TargetType="{x:Type DataGridRow}">
                                        <Setter Property="Background" Value="{Binding Path=., Converter={StaticResource MultipleValidatorConverter}, ConverterParameter=LAR}"/>
                                    </Style>
                                </DataGridTemplateColumn.CellStyle>

And then the converter would look similar to this:

public class MultipleValidatorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        classNameUsedForItemsSource row = value as classNameUsedForItemsSource ;
        string param = parameter as string;

        if(param == "LAR")
        {
            if (param.Length < 8) return Brushes.Red;
        }
        // Other checks here based on parameter

        return DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

But sadly this throws an error saying DataGridRow does not match targettype DataGridCell and now I am stuck. Looked on google and here but not able to find a match for my requirement.

I don't believe you can bind columns to the parameters for a converter so I can't pursue that, I really need to pass the whole row so I can check other related fields OR pass multiple bindings to the converter.

Upvotes: 0

Views: 855

Answers (1)

R. Wood
R. Wood

Reputation: 101

Despite the helpful comment, whilst the validation then worked it did not refresh the cell style after editing. Therefore I changed my method and used the following solution instead using a multi value converter.

public class IlrMultipleValidatorConverter : IMultiValueConverter
{
    public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string param = parameter as string;

        if (param == "LAR")
        {
            string lar = value[0] as string;
            if (lar == null || lar == "") return Brushes.Red;
            else
            {
                if (lar.Length > 8) return Brushes.Red;
            }
        }
        if (param == "PwayCode")
        {
            string pway = value[0] as string;
            string ptype = value[1] as string;

            if (pway == null || pway == "")
            {
                if (ptype == "2" || ptype == "3" || ptype == "10" || ptype == "20" || ptype == "21" || ptype == "22" || ptype == "23") return Brushes.Red;
            }
        }


        return DependencyProperty.UnsetValue;
    }

    public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

This lets me add more conditions as I go for the same grid and setting each style for validation was done like so:

<DataGridTemplateColumn.CellStyle>
    <Style TargetType="{x:Type DataGridCell}">
        <Setter Property="Background">
           <Setter.Value>
              <MultiBinding>
                  <MultiBinding.Converter>
                       <local:IlrMultipleValidatorConverter />
                  </MultiBinding.Converter>
                  <MultiBinding.ConverterParameter>PwayCode</MultiBinding.ConverterParameter>
                  <Binding Path="ApprenticeshipPathway" />
                  <Binding Path="ProgrammeType" />
              </MultiBinding>
           </Setter.Value>
       </Setter>
    </Style>
</DataGridTemplateColumn.CellStyle>

Upvotes: 0

Related Questions