13

Using C#.Net 4.5, Visual Studio 2012 Ulti, WPF.

I've got some old win-forms code that i wanted to do in this new WPF app.

code is the following:

DataGridViewImageCell pNew = new DataGridViewImageCell();

ParetoGrid.Columns.Add(new DataGridViewImageColumn() { CellTemplate = pNew, FillWeight = 1, HeaderText = "pNew", Name = "pNew", Width = 30 });

ParetoGrid.Columns["pNew"].DisplayIndex = 18;

3 lines of code to add a column that can handle images. In WPF I've seen its a bit different. Do i need to add an "image column"? or does WPF columns support images? or is there another 3 liner solution that is simply different syntax?

Thanks for the help guys

lemunk
  • 2,616
  • 12
  • 57
  • 87
  • 1
    WPF allows you to pretty much put anything you want inside controls. You can put an entire custom control in a column, or primitive types – JeremyK Mar 28 '13 at 13:37
  • wow, so basically i can skip this part, simply add a new column and the add images to that column? no need for a specified column type? – lemunk Mar 28 '13 at 13:38
  • You would simply bind the variable to the column and it will load that image from the object you add to the row – JeremyK Mar 28 '13 at 13:40

4 Answers4

24

See this answer:

Image Column in WPF DataGrid

 <DataGridTemplateColumn Header="Image" Width="SizeToCells"
 IsReadOnly="True">
   <DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
           <Image Source="{Binding Image}" />
      </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
 </DataGridTemplateColumn>

To add a column in code after:

DataGridTextColumn textColumn1 = new DataGridTextColumn();
textColumn1.Header = "Your header";
textColumn1.Binding = new Binding("YourBindingField");
dg.Columns.Add(textColumn1);

Use DataGridTemplateColumn to add a custom column See: How do I show image in wpf datagrid column programmatically?

Community
  • 1
  • 1
JeremyK
  • 1,075
  • 1
  • 22
  • 45
  • ohh using xaml...if at all possible I wanted to avoid xaml and stick to the c# code behind or is that just bad practice in wpf? – lemunk Mar 28 '13 at 13:42
  • 2
    WPF was created to use XAML. It makes life easier and leaves no reason to do the coding yourself :) You could always view the automated source code after you create the xaml to see what is being done behind the scenes to make it happen – JeremyK Mar 28 '13 at 13:43
  • well the datgrid will need 3 new columns that are generated at runtime purely for the user. then each row is calculated using a formula and then the correct image is diaplyed in these new columsn per row depending on the formula outcome. this example seems static to me or am I simply failing to understand? – lemunk Mar 28 '13 at 13:46
  • You can create it in code as well, or create the image column in xaml since you know its there and add the others after the fact – JeremyK Mar 28 '13 at 13:48
  • For other newbies reading. Yes @lemunk was failing to understand as he suggested. It doesn't need to be static. Bindings will decide the image to be displayed at runtime. – Ozgur Ozturk Aug 10 '15 at 14:53
5

Here is what I did. Add a datatemplate in your datagrid with image control like this

            <DataGridTemplateColumn Header="File Type" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Image Height="25" Width="50" Source="{Binding FileIcon}"  />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

As you can see my I am binding Image with a property named "FileIcon" that is used in class Version like this

            public class Version
            {
              public string FileIcon { get; set; }
            }

Now only this you have to do is bind provide a path to "FileIcon" and update ItemSource of DataGrid like this

            ObservableCollection<Version> items = new ObservableCollection<Version>();

            items.Add(new Version()
            {
                FileIcon = "/AssemblyName;component/Images/eye.png",
            });
            YourDataGrid.ItemsSource = null;
            YourDataGrid.ItemsSource = items;
Hadeed Ullah
  • 51
  • 1
  • 1
2

Here is MainWindow.xaml's code just simple for better understanding

`

<Window x:Class="Pic_in_Datagrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Pic_in_Datagrid"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

    <Grid>
        <DataGrid x:Name="dt1" ColumnWidth="*" AutoGenerateColumns="False">

        </DataGrid>
    </Grid>
</Window>

After it here is my MainWindow.xaml.cs's code for image or text for adding in datadrid dynamically...

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Windows.Controls;    
namespace Pic_in_Datagrid
        {
            /// <summary>
            /// Interaction logic for MainWindow.xaml
            /// </summary>
            public partial class MainWindow : Window
            {
                public StudentData stu_data { get; set; }
                public MainWindow()
                {
                    InitializeComponent();
                    stu_data = new StudentData();

                    List<StudentData> stu = new List<StudentData>();
                    stu.Add(new StudentData() { image = toBitmap(File.ReadAllBytes(@"D:\1.jpg")), stu_name = "abc" });
                    stu.Add(new StudentData() { image = toBitmap(File.ReadAllBytes(@"D:\1.jpg")), stu_name = "def" });



                    FrameworkElementFactory factory = new FrameworkElementFactory(typeof(System.Windows.Controls.Image));
                    Binding bind = new System.Windows.Data.Binding("image");//please keep "image" name as you have set in your class data member name
                    factory.SetValue(System.Windows.Controls.Image.SourceProperty, bind);
                    DataTemplate cellTemplate = new DataTemplate() { VisualTree = factory };
                    DataGridTemplateColumn imgCol = new DataGridTemplateColumn()
                    {
                        Header = "image", //this is upto you whatever you want to keep, this will be shown on column to represent the data for helping the user...
                        CellTemplate = cellTemplate
                    };
                    dt1.Columns.Add(imgCol);

                    dt1.Columns.Add(new DataGridTextColumn()
                    {
                        Header = "student name",
                        Binding = new Binding("stu_name") //please keep "stu_name" as you have set in class datamember name
                    });

                    dt1.ItemsSource = stu;    
                }

                public static BitmapImage toBitmap(Byte[] value)
                {
                    if (value != null && value is byte[])
                    {
                        byte[] ByteArray = value as byte[];
                        BitmapImage bmp = new BitmapImage();
                        bmp.BeginInit();
                        bmp.StreamSource = new MemoryStream(ByteArray);
                        bmp.EndInit();
                        return bmp;
                    }
                    return null;
                }
            }

           public class StudentData
           {
                    public BitmapImage image { get; set; }
                    public string stu_name { get; set; }
            }
        }

The above all code is taken from different resources... Thanks to them who developed and shared these codes...

0

You may try add Image to DataGridTextColumn via pattern bellow. You may sorting and copy to clipboard works well. Use your converter, or binding to your property.

<DataGridTextColumn  Header="Level"  IsReadOnly="True" Binding="{Binding Level,Converter={StaticResource LogLevelStringConverter}}"   >
    <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell" >
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="DataGridCell">
                        <Grid Background="{TemplateBinding Background}" >
                            <ContentPresenter VerticalAlignment="Center" Margin="20,0,0,0" HorizontalAlignment="Left"  />
                            <Image Grid.Column="0" Width="18" Height="18" Source="{Binding Level,Converter={StaticResource LogLevelIconConverter}}"  HorizontalAlignment="Left" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>
lison
  • 189
  • 1
  • 6