简体   繁体   中英

WPF DataGrid display 'NULL' when bound property is null

I'm trying to display a cell containing a 'NULL' string instead of a blank cell when the corresponding source value is null. I'm using a DataGrid bound to a DataTable and AutoGenerateColumns="True" .

Previously I managed to do it in the code-behind through the AutoGeneratedColumns event, but now I've switched to MVVM design and I wanted to avoid this.

foreach (var column in dgwCustomTableSelected.Columns)
{
    if (column is DataGridTextColumn) 
    {
        ((DataGridTextColumn)column).Binding = 
            new Binding() { 
                Converter = new NullValueConverter((string)column.Header) 
            };
    }
}

I was wondering whether there's a way to associate a Converter to all the datagrid columns or any other feasible solution to this.

Thanks in advance

I was wondering whether there's a way to associate a Converter to all the datagrid columns or any other feasible solution to this.

The "feasible solution" would be to handle the AutoGeneratingColumn event in the view. Or define all columns explicitly in the XAML markup of the same view.

Neither approach breaks the MVVM pattern since this is view-related functionality and MVVM is not about eliminating view-related code from the views. It is mainly about separation of concerns and doing view-related things programmatically instead of doing it in the XAML markup is perfectly fine.

I would try to do it in the ViewModel . Lets say your ViewModel class would look something like this (I left INotofyPropertyChanged out for simplicity):

public class ViewModel
{
    private ModelClass model = new ModelClass();

    public string Name
    {
       get
       {
           return model.Name;
       }
       set
       {
           model.name = value;
       }
    }
}

You could refactor it to something like this:

public class ViewModel
{
    private ModelClass model = new ModelClass();

    public string Name
    {
       get
       {
           if(model.Name == null)
           {
              return "NULL";
           }

           return model.Name;
       }
       set
       {
           model.name = value;
       }
    }
}

You could also try Custom Markup Extension that will allow you to include Converter inside of the Binding . For that to work you would also have to create DataTemplates for different types of data but overall gain, namely handling the data types, would outweigh the amount of coding. Here is an example of said Markup Extension from searchwindevelopment

class NumberToBrushConverter : MarkupExtension, IValueConverter
{
    private static NumberToBrushConverter _converter = null;

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        // determine if we have an instance of converter
        // return converter to client
        return _converter ?? (_converter = new NumberToBrushConverter());
    }
    public object Convert(object value, Type targetType,
                      object parameter,CultureInfo culture)
    {

        return new SolidColorBrush(Colors.Orange);
    }

    public object ConvertBack(object value, Type targetType, 
                          object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

  }  

Then in xaml you would use it like this:

<Window x:Class="ValueConverterTips.CustomMarkupTip"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:converters='clr-namespace:ValueConverterTips.Converters'
    Title="CustomMarkupTip" >

    <!-- no longer need the resources section -->

    <Grid>
        <Ellipse Fill='{Binding SomeIntData,  
         Converter={converters:NumberToBrushConverter}}'
         Width='10' Height='10' />
    </Grid>
</Window>  

You would have to modify this to suit your scenario.
EDIT
This is how you would use this with AutoGenerateColumns=true :

<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate>
            <Button Content="Ok"/>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

<DataGrid AutGenerateColumns="true" ItemsSource={Binding xxx} etc...>

</DataGrid>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM