Search code examples
c#wpfwpf-controlswpfdatagrid

How to bind an 2D array bool[][] to a WPF DataGrid (one-way)?


I have a matrix kind datagrid like this.

enter image description here

this grid is designed entirely in XAML

Now how to insert values into these datagridcell with 2 dimensional array ? the values which is needed to be inserted must be of bool datatype (either TRUE or FALSE). Any ideas ?


Solution

  • Here is my approach for a MVVM scenario, using a converter which creates a DataView which can be bound to the grids ItemsSource. It's for a special Matrix datatype which holds doubles, but you'll be able to modify it yourself for your requirements:

    public class MatrixToDataViewConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var array = value as Matrix;
            if (array == null) return null;
    
            //var array = ILMath.rand(3, 5);
    
            var rows = array.Dimensions[0];
            var columns = array.Dimensions[1];
    
            var t = new DataTable();
            for (var c = 0; c < columns; c++)
            {
                t.Columns.Add(new DataColumn(c.ToString()));
            }
    
            for (var r = 0; r < rows; r++)
            {
                var newRow = t.NewRow();
                for (var c = 0; c < columns; c++)
                {
                    var v = array[r, c];
    
                    // Round if parameter is set
                    if (parameter != null)
                    {
                        int digits;
                        if (int.TryParse(parameter.ToString(), out digits))
                            v = Math.Round(v, digits);
                    }
    
                    newRow[c] = v;
                }
    
                t.Rows.Add(newRow);
            }
    
    
            return t.DefaultView;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    Define a resource for the converter:

    <converter:MatrixToDataViewConverter x:Key="MatrixToDataViewConverter" />
    

    And use it like this:

    <DataGrid ItemsSource="{Binding Matrix, Converter={StaticResource MatrixToDataViewConverter}, ConverterParameter=1}"/>
    

    It doesn't allow two way binding, though...

    EDIT

    Here's the version for an array bool[][]:

    public class BoolArrayToDataViewConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var array = value as bool[,];
            if (array == null) return null;
    
            var rows = array.GetLength(0);
            if (rows == 0) return null;
    
            var columns = array.GetLength(1);
            if (columns == 0) return null;
    
            var t = new DataTable();
    
            // Add columns with name "0", "1", "2", ...
            for (var c = 0; c < columns; c++)
            {
                t.Columns.Add(new DataColumn(c.ToString()));
            }
    
            // Add data to DataTable
            for (var r = 0; r < rows; r++)
            {
                var newRow = t.NewRow();
                for (var c = 0; c < columns; c++)
                {
                    newRow[c] = array[r, c];
                }
                t.Rows.Add(newRow);
            }
    
            return t.DefaultView;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    and the usage:

    <DataGrid ItemsSource="{Binding Matrix, Converter={StaticResource BoolArrayToDataViewConverter}}"/>
    

    And this is what it looks like in the very raw version. You can then style the DataGrid and edit it's templates, but this is another question...

    UI