0

I want to bind a DataTable to DataGrid with mixed text and images. I use Material Design in XAML and .NET Community Toolkit 8.0 MVVM.

My View:

    <Grid>
        <DataGrid ItemsSource="{Binding DataTableContent}" />
    </Grid>

My ViewModel

public partial class ViewModel : ObservableObject
    {

        [ObservableProperty]
        DataTable _dataTableContent;

        public ViewModel()
        {
            _dataTableContent = new DataTable();
            _dataTableContent.Columns.Add("Test123");
            _dataTableContent.Rows.Add("A");
            _dataTableContent.Rows.Add(PackIconKind.Printer);
        }
    }

How can I use the Icon in a DataTable. I found a few examples how to use them in XAML directly but that doesn't seem to help in my case.

Thank you in advance!

Enki
  • 77
  • 7
  • Does the binding work at the first place?! – Muhammad Sulaiman Sep 06 '22 at 03:03
  • I don't see the definition of the `DataTable` : `_dataTableContent.Columns.Add("ColumnA", typeof(string));` `_dataTableContent.Columns.Add("ColumnB", typeof(byte[]));` . You can Add the Printer icon from MaterialIconPack as byte[] in your DataTable, then in the Model or in ViewModel add a byte[] Property that will store the data from datatable's row. I suggest implementation of [MVVM pattern](https://learn.microsoft.com/en-us/archive/msdn-magazine/2009/february/patterns-wpf-apps-with-the-model-view-viewmodel-design-pattern). – Vali Maties Sep 06 '22 at 06:01
  • @MuhammadSulaiman yes. The `.NET Community Toolkit 8.0` helps a lot and auto generate the boilerplate code. – Enki Sep 06 '22 at 06:48
  • @ValiMatieș - I use mvvm pattern. I use `.NET Community Toolkit 8.0` which helps a lot and generates boilerplate code. That's the reason why my code seems "naked". You wrote: "You can Add the Printer icon from MaterialIconPack as byte[]" <- How do I do that? – Enki Sep 06 '22 at 06:54
  • @Enki , create a `PackIcon` object and assign the Kind you want to it. The `PackIcon.Data` is string representation of a `Geometry`. Parse that string in a `Geometry` object, using `Geometry.Parse()` method, then using [the answer](https://stackoverflow.com/questions/9080231/how-to-save-geometry-as-image) from this link, but modified to save to a MemoryStream, not to a File, you could return a byte[]. – Vali Maties Sep 06 '22 at 10:48
  • But sincerely, I don't know why you tell it doesn't help you.. I don't think you need anything else than a Template to your DataGrid to show an image to the second column, not all the conversions I told you before... – Vali Maties Sep 06 '22 at 11:33
  • @ValiMatieș Because you say "I don't think you need anything else than a Template to your DataGrid...". When I read your answer above, I did the following thing: ```csharp _dataTableContent = new DataTable(); _dataTableContent.Columns.Add("Test123", typeof(string)); _dataTableContent.Columns.Add("Icon", typeof(byte[])); _dataTableContent.Rows.Add("A", PackIconKind.Printer); ``` runtime exception: System.ArgumentException: 'Type of value has a mismatch with column typeCouldn't store in Icon Column. Expected type is Byte[].' – Enki Sep 06 '22 at 21:01
  • PackIconKind.Printer is a `PackIconKind` type. You must first convert that PackIconKind to byte[] to be able to insert in datatable, as I mention in the comment from Sep 6 at 10:48. But the solution is to set the type in second column as `PackIconKind`, not byte[] and to template your DataGrid in xaml to display that Kind. You use WPF, not WinForms. Is not a good idea to do all the job in cs code, but in xaml. – Vali Maties Sep 12 '22 at 11:16
  • The problem is that I have to do it in .cs code because my datatable is dynamic. – Enki Sep 13 '22 at 15:33

1 Answers1

0

If you can disable AutoGenerateColumns that helps:

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Data}" >  


<DataGrid.Columns>
    <DataGridTemplateColumn>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ContentPresenter Content="{Binding Name}" />    
        </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>                           
</DataGridTemplateColumn>  

    <DataGridTemplateColumn>  
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>  
                <ContentPresenter Content="{Binding BooleanValue}" />      
            </DataTemplate>  
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>  

    <DataGridTemplateColumn>  
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>  
                <ContentPresenter Content="{Binding Icon}" />          
            </DataTemplate>  
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>  

</DataGrid.Columns>

</DataGrid>  
Enki
  • 77
  • 7