This is my datagrid i want to display an image in the grid column but its is showing me text System.Windows.Media.Imaging.BitmapImage, instead of displaying an Image.
How to add an image in a datagrid column?
This is what I have tried :
Dictionary dict1=new Dictionary < string,object>();
string keyimage="Image";
object a1 = new BitmapImage();
a1=Imaging.CreateBitmapSourceFromHIcon(SystemIcons.Information.Handle, Int32Rect.Empty, null);
dict1.Add(keyimage, a1);
This dict1 serves as Itemsource for the datagrid...........how to make an image to be displayed in a datagrid column?
Make sure you use a DataGridTemplateColumn and put an image into it.
Since you are using a dictionary, bind the value, something like:
<Image Binding="{Binding Height="25" Width="50" Source="{Binding Value}" />
I suppose your Column datatype mismatches with itemsource datatype. You have to make equal datatype Image for both Grid Column and itemsource.
In my WPF project I made my column data template with Images:
DataTable dtab = new DataTable();
dtab.Columns.Add("imageColumn", typeof(BitmapImage));
//Uploading dtab with Images from DataBase
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(Image));
Binding bind = new System.Windows.Data.Binding("imageColumn");
factory.SetValue(Image.SourceProperty, bind);
DataTemplate cellTemplate = new DataTemplate() { VisualTree = factory };
DataGridTemplateColumn imgCol = new DataGridTemplateColumn()
{
Header="image",
CellTemplate = cellTemplate
};
DataGrid dg = new DataGrid();
dg.Columns.Add(imgCol);
dg.ItemsSource = dtab.DefaultView;
Hope this help
Add any image to your Project on Resource folder
After that try the below coding in DataGrid Bind event. Here i have add the image logo...
DataGridViewImageColumn imageColoumn = new DataGridViewImageColumn();
imageColoumn.HeaderText = "Img";
imageColoumn.Image = null;
imageColoumn.Name = "DataPic";
imageColoumn.Width = 150;
dataGridView1.Columns.Add(imageColoumn);
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataGridViewImageCell cell = row.Cells[1] as DataGridViewImageCell;
cell.Value = (System.Drawing.Image)Properties.Resources.logo;
}
Related
I am creating and binding columns/elements into my datagrid.
I created a DataGridTemplateColumnand in that column i'm inserting a TextBox element.
DataGridTemplateColumn columnFeedbackSupplier = new DataGridTemplateColumn();
var dockPanel = new FrameworkElementFactory(typeof(DockPanel));
DataTemplate cellTemplate = new DataTemplate();
FrameworkElementFactory factoryText = new FrameworkElementFactory(typeof(TextBox));
Binding bindText = new Binding("Supplier");
bindText.Mode = BindingMode.TwoWay;
factoryText.SetValue(TextBox.TextProperty, bindText);
//This is not working
factoryText.SetValue(TextBox.VisibilityProperty, Visibility.Visible);
//
cellTemplate.VisualTree = factoryText;
dockPanel.AppendChild(factoryText);
cellTemplate.VisualTree = dockPanel;
Now when I add the following line, it allows me to edit my selected cell, but it also hides my TextBox on my datagrid until I double click on that cell then my element is visible again. Once that cell loses focus, my TextBox is hidden again.
columnFeedbackSupplier.CellEditingTemplate = cellTemplate;
I can use the following line to make my TextBox always visible, but I would not be able to save my edited values into my datagrid.
columnFeedbackSupplier.CellTemplate = cellTemplate;
Is there a way to make my TextBox always visible, while using CellEditingTemplate?
I've been looking everywhere for proper documentation on the internet about the FrameworkElementFactory class, but I cannot seem to find proper tutorials or useful information on it.
Can someone that knows a bit more about this subject give me more information on it please? Here is what i've found so far from THIS question: (Thanks to Bob)
Bind the ItemsSource to myDataGrid:
Binding dataGridItemsSourceBinding = new Binding("MyItemsSourceName");
myDataGrid.SetBinding(DataGrid.ItemsSourceProperty, datagridItemsSourceBinding);
Create a DataGridTemplateColumn
DataGridTemplateColumn templatecolumn = new DataGridTemplateColumn() {
Header = "myColumnName", // Add the name of your column here
};
Create the Data Template for when you are displaying the value in the DataCell for the DataGrid Column
// Displaying Template for when you display the DataCell in the DataGridColumn
// Create a Data Template for when you are displaying a DataGridColumn
DataTemplate textBlockTemplate = new DataTemplate();
// Create a Framework Element for the DataGridColumn type (In this case, a TextBlock)
FrameworkElementFactory textBlockElement = new FrameworkElementFactory(typeof(TextBlock));
// Create a Binding to the value being displayed in the DataGridColumn
Binding textBlockBinding = new Binding("myPropertyName");
// Assign the Binding to the Text Property of the TextBlock
textBlockElement.SetBinding(TextBlock.TextProperty, textBlockBinding);
// Set the DataGridColumn to stretch to fit the text
textBlockElement.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
// Add the TextBlock element to the Visual Tree of the Data Template
textBlockTemplate.VisualTree = textBlockElement;
// Add the Data Template to the DataGridColumn Cell Template
templatecolumn.CellTemplate = textBlockTemplate;
Create the Data Template for when you are editing the value in the DataCell for the DataGrid Column
// Editing Template for when you edit the DataCell in the DataGridColumn
// Create a Data Template for when you are displaying a DataGridColumn
DataTemplate textBoxTemplate = new DataTemplate();
// Create a Framework Element for the DataGrid Column type (In this case, TextBox so the user can type)
FrameworkElementFactory textBoxElement = new FrameworkElementFactory(typeof(TextBox));
// Create a Binding to the value being edited in the DataGridColumn
Binding textBoxBinding = new Binding("myPropertyName");
// Assign the Binding to the Text Property of the TextBox
textBoxElement.SetBinding(TextBox.TextProperty, textBoxBinding);
// Set the DataGridColumn to stretch to fit the text
textBlockElement.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
// Add the TextBox element to the Visual Tree of the Data Template
textBoxTemplate.VisualTree = textBoxElement;
// Add the Data Template to the DataGridColumn Cell Editing Template
templatecolumn.CellEditingTemplate = textBoxTemplate;
Add the completed DataGridColumn to your DataGrid
// Add the completed DataGridColumn to your DataGrid
myDataGrid.Columns.Add(templateColumn);
Please refer to this thread: Purpose of using FrameworkElementFactory
As for now Microsoft does not recommend using the FrameworkElementFactory
This part works.
In my C#.NET WPF XAML, I have a static ComboBox and a static TextBox. The TextBox displays another column from the same DataTable (in the ComboBox's ItemSource). The column "rr_code" is the column for company name and the column "rr_addr" is the column for the address.
<ComboBox x:Name="CompanyComboBox1" IsEditable="True" IsTextSearchEnabled="True" IsSynchronizedWithCurrentItem="False"/>
<TextBox x:Name="StreetTextBox1" DataContext="{Binding SelectedItem, ElementName=CompanyComboBox1}" Text="{Binding rr_addr}" IsManipulationEnabled="True"\>
The ComboBox reads programmatically from a column in a DataTable:
CompanyComboBox1.ItemsSource = Rails.DefaultView; // Rails is a DataTable
CompanyComboBox1.DisplayMemberPath = "rr_code"; // column name for company name
This part doesn't work
The question is, I now have a "Add Company" button that creates a new form in a StackPanel, dynamically and with this exact functionality. The ComboBox works exactly as expected. Here's what I have so far:
ComboBox companyComboBox = new ComboBox();
companyComboBox.ItemsSource = Rails.DefaultView;
companyComboBox.IsEditable = true;
companyComboBox.IsTextSearchEnabled = true;
companyComboBox.DisplayMemberPath = "rr_code";
The problem is in the TextBox, which is not updating when I change the dynamic companyComboBox, so I'm sure it has to do with the binding.
TextBox streetTextBox = new TextBox();
streetTextBox.DataContext = companyComboBox;
Binding b = new Binding("rr_addr");
b.Mode = BindingMode.Default;
b.Source = companyComboBox.SelectedItem;
streetTextBox.SetBinding(ComboBox.SelectedItemProperty, b);
What is the correct way to set the binding for the TextBox streetTextBox?
The code-behind equivalent of this particular XAML + C# data binding in pure C# is:
ComboBox companyComboBox = new ComboBox();
companyComboBox.ItemsSource = Rails.DefaultView; // Rails being DataTable
companyComboBox.IsEditable = true;
companyComboBox.IsTextSearchEnabled = true;
companyComboBox.DisplayMemberPath = "rr_code";
Binding b = new Binding("SelectedItem.rr_addr"); // The selected item's 'rr_addr' column ...
b.Source = companyComboBox; // ... of the companyComboBox ...
TextBox streetTextBox = new TextBox();
streetTextBox.SetBinding(TextBox.TextProperty,b); // ... is bound to streetTextBox's Text property.
The error was in the last line. SetBinding needed to have a property of the target, not the source. In addition, the Binding declaration needed "SelectedItem." for some reason.
Why are you setting the TextBox DataContext ?
You can simply bind TextBox.Text property to ComboBox SelectedItem in your XAML
<TextBox Text="{Binding ElementName=CompanyComboBox1, Path=SelectedItem.rr_addr}"></TextBox>
I create a DataGrid object in my code behind and set the content with obj.ItemsSource.
Now I would like to set the background color of one specific row in the code behind. How can I achieve this?
Update:
I create the DataGrid object in the code behind like following:
var dataGrid = new DataGrid();
dataGrid.ItemsSource = BuildDataGrid(); // Has at least one row
var row = (DataGridRow) dataGrid.ItemContainerGenerator.ContainerFromIndex(0);
row.Background = Brushes.Red;
But the row object is null. Why is that?
You can get the DataGridRow using ItemContainerGenerator of dataGrid.
In case you want to select row based on index value, use ContainerFromIndex() method:
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator
.ContainerFromIndex(0);
and in case want to get row based on item, use ContainerFromItem() method:
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator
.ContainerFromItem(item);
Finally set background on row:
row.Background = Brushes.Red;
UPDATE:
Containers are not generated till dataGrid is not visible on GUI. You need to wait for containers to be generated before you can set any property on DataGridRow.
By container i meant DataGridRow in case of DataGrid. You need to modify your code like this:
var dataGrid = new DataGrid();
dataGrid.ItemsSource = BuildDataGrid();
dataGrid.ItemContainerGenerator.StatusChanged += (s, e) =>
{
if (dataGrid.ItemContainerGenerator.Status ==
GeneratorStatus.ContainersGenerated)
{
var row = (DataGridRow)dataGrid.ItemContainerGenerator
.ContainerFromIndex(0);
row.Background = Brushes.Red;
}
};
I need to copy a DataGrid removing the last column. I tried with this code and it sets the ItemSource correctly, but the columns are empty (in some case I bind object.property):
DataGrid dg = new DataGrid();
foreach (DataGridColumn dgColumns in source.Columns.Where(i => i.Header != "Sending Result"))
{
dg.Columns.Add(new DataGridTextColumn
{
Width = dgColumns.Width,
Header = dgColumns.Header,
Binding = new Binding(string.Format("{0}", dgColumns.SortMemberPath)));
}
}
dg.ItemsSource = source.ItemsSource;
Can anyone help me with this problem? Thank you in advance.
Your problem I think is that you are setting the ItemsSource property property before you are adding your grid into the logical tree.
Try adding the grid to its new parent, and then setting the ItemsSource.