Change gridview column header's BackColor - winforms

Successfully,placed an image on one of the column headers of my gridview.But its backcolor is all white now, unlike other column headers which are grey, the default back color.How can I change/paint the white to grey.
private void GridViewSale_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex < 0 && e.ColumnIndex == 1)
{
Rectangle rec = new Rectangle(4, 5, 14, 14);
e.Graphics.DrawImage(Properties.Resources.DelOn, rec);
e.Handled = true;
e.CellStyle.BackColor = Color.DeepPink; (//Not working)
}
}

First Set EnableHeadersVisualStyles="false" inside your DataGridView.Then,
DataGridViewColumn gridviewColumnName = yourGridviewName.Columns[0]; // will set the first column
gridviewColumnName .HeaderCell.Style.BackColor = Color.DeepPink;

Related

Overridden CellPainting in DataGridView displays content only after cell loses focus

I have overridden the CellPainting in a WinForms DataGridView to display a specific image in a cell depending on various factors.
To give you some more details, in the CellPainting I am redrawing the content of a DataGricViewCheckBoxColumn; I want to display a green tick or red cross instead of the default black tick.
To draw the image I use:
e.Graphics.DrawImage(image, new PointF(centreX - offsetX, centreY - offsetY));
It works fine, but my green tick/red cross is only displayed after the cell loses focus. Is there a way to make it show as soon as I have clicked it, just like the standard checkbox does?
Thanks
Handle the CellContentClick event to toggle the value (true/false) of the current cell. The CellContent of a DataGridViewCheckBoxColumn is the check box.
Assuming the DataGridViewCheckBoxColumn is the first column:
private void dgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
{
var s = sender as DataGridView;
var b = s[e.ColumnIndex, e.RowIndex].Value == null
? true
: (bool)s[e.ColumnIndex, e.RowIndex].Value;
s[e.ColumnIndex, e.RowIndex].Value = !b;
}
}
If you prefer to toggle the value by clicking anywhere on the cell (not over the check box only), handle the CellMouseClick instead:
private void dgv_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Left && e.ColumnIndex == 0 && e.RowIndex >= 0)
{
var s = sender as DataGridView;
var b = s[e.ColumnIndex, e.RowIndex].Value == null
? true
: (bool)s[e.ColumnIndex, e.RowIndex].Value;
s[e.ColumnIndex, e.RowIndex].Value = !b;
s.NotifyCurrentCellDirty(true);
}
}
Either way, the CellPainting event fires and the specified image is drawn as you click.
CellPainting example:
Bitmap bmp1 = Properties.Resources.GreenImage;
Bitmap bmp2 = Properties.Resources.RedImage;
private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
{
var s = sender as DataGridView;
e.Paint(e.CellBounds, DataGridViewPaintParts.Background
| DataGridViewPaintParts.Border
| DataGridViewPaintParts.SelectionBackground
| DataGridViewPaintParts.Focus
| DataGridViewPaintParts.ErrorIcon);
if (e.Value != null)
{
var r = new Rectangle((e.CellBounds.Width - 16) / 2 + e.CellBounds.X,
(e.CellBounds.Height - 16) / 2 + e.CellBounds.Y, 16, 16);
var b = (bool)e.Value;
e.Graphics.DrawImage(b ? bmp1 : bmp2, r);
}
e.Handled = true;
}
}

DataGridView Custom control enable button in Unedited mode

Does anyone know how to get the button visible all the time?.(Not only in edit mode of the cell)
I would like to take your attention to the answer of this question.
how to add ellipse button and textbox in current cell of datagridview in winforms
I could enhance this solution to see the button control in the cell for all the time. What I want is to get the popup box for the first click of the cell. This is the code to paint the button in uneditted mode.
// Finally paint the NumericUpDown control
Rectangle srcRect = new Rectangle(0, 0, valBounds.Width, valBounds.Height);
if (srcRect.Width > 0 && srcRect.Height > 0)
{
Bitmap renderingBitmap = new Bitmap(22, 18);
new TextButton().button.DrawToBitmap(renderingBitmap, srcRect);
graphics.DrawImage(renderingBitmap, new Rectangle(new Point(cellBounds.X+cellBounds.Width-24, valBounds.Location.Y-2), valBounds.Size),
srcRect, GraphicsUnit.Pixel);
}
A better option would be to embed a button on your DataGridView. This would give you more control over the use of DataGridView. See the following snippet:
Button b1 = new Button();
int cRow = 0, cCol = 0;
private void Form1_Load(object sender, EventArgs e)
{
b1.Text = "...";
b1.Visible = false;
this.dataGridView1.Controls.Add(b1);
b1.BringToFront();
this.dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint);
this.b1.Click += new EventHandler(b1_Click);
}
void b1_Click(object sender, EventArgs e)
{
//Implement your logic here
}
void dataGridView1_Paint(object sender, PaintEventArgs e)
{
if(cRow != 0 && cCol != 0)
{
Rectangle rect = new Rectangle();
rect = dataGridView1.GetCellDisplayRectangle(cRow ,cCol , false);
rect.X = rect.X + (2*dataGridView1.Columns[1].Width / 3);
rect.Width = dataGridView1.Columns[1].Width / 3;
b1.Bounds = rect;
b1.Visible = true;
}
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
cRow = e.RowIndex;
cCol = e.ColumnIndex;
}
In the above snippet the location of ellipses button is set to last clicked cell. The visibility is always true after a cell is clicked. In my opinion this would provide a far better control over the button's function,and is easier to maintain.

How to change the border color of some cells in DataGridView?

I need to programming change the border color of some cells in the CellFormatting event. Can the board color of an individual cell be changed?
You can draw a rectangle. In this example I put a red boder on the selected cells.
private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
{
if (dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected == true)
{
e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Border);
using (Pen p = new Pen(Color.Red, 1))
{
Rectangle rect = e.CellBounds;
rect.Width -= 2;
rect.Height -= 2;
e.Graphics.DrawRectangle(p, rect);
}
e.Handled = true;
}
}
}
MSDN describes a method where you can inherit from the DataGridView to override the default border styles: DataGridViewAdvancedBorderStyle Class
The painting method above is simpler, though.

DataGrid select last cell programmatically

When the DataGrid below gets the focus for the first time and only the first time (ie, after some other control has had the focus), the last row, 2nd column should be focused and in edit.
I added a handler for the DataGrid.GotFocus, but it's complicated code and not getting the result above.
Anyone got an elegant, bullet proof solution?
I made tiny modifications to the code
the sender should always be the grid I want, so I just used that instead of relying on a name
When the SelectionUnit is FullRow, as my grid was before I changed it to CellOrRowHeader you
apparently can't call SelectedCells.Clear()
Code below:
private void OnDataGridKeyboardGotFocus(object sender, KeyboardFocusChangedEventArgs e)
{
var dg = sender as DataGrid;
if (_hasHadInitialFocus) return;
var rowIndex = dg.Items.Count - 2;
if (rowIndex >= 0 && dg.Columns.Count - 1 >= 0)
{
var column = dg.Columns[dg.Columns.Count - 1];
var item = dg.Items[rowIndex];
var dataGridCellInfo = new DataGridCellInfo(item, column);
if (dg.SelectionUnit != DataGridSelectionUnit.FullRow) {
dg.SelectedCells.Clear();
dg.SelectedCells.Add(dataGridCellInfo);
}
else {
var row = dg.GetRow(rowIndex);
row.IsSelected = true;
}
dg.CurrentCell = dataGridCellInfo;
dg.BeginEdit();
}
_hasHadInitialFocus = true;
}
New Question
I want to repeat the selection when the focus goes to another control in the window and then back to the grid.
I thought I could turn that _hasHadInitialFocus latch to false in a LostFocus event, but the code below is firing on cell changes.
Do you know how I should be trapping the lost focus event better, and do you agree that is the place to turn the latch off?
private void DataGridLostFocus(object sender, RoutedEventArgs e) {
_hasHadInitialFocus = false;
}
You may have to fiddle with the offsets depending on whether there's an new item row visible or not, but this works for me.
private bool _hasHadInitialFocus;
private void DataGridGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (!_hasHadInitialFocus)
{
if (dataGrid.Items.Count - 2 >= 0 && dataGrid.Columns.Count - 1 >= 0)
{
var dataGridCellInfo = new DataGridCellInfo(
dataGrid.Items[dataGrid.Items.Count - 2], dataGrid.Columns[dataGrid.Columns.Count - 1]);
dataGrid.SelectedCells.Clear();
dataGrid.SelectedCells.Add(dataGridCellInfo);
dataGrid.CurrentCell = dataGridCellInfo;
dataGrid.BeginEdit();
}
_hasHadInitialFocus = true;
}
}
I noticed that clicking into the grid leaves one cell selected and the target cell in edit mode. A solution to this if required is:
private void DataGridGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
EditCell();
}
private void PreviewMouseLBDown(object sender, MouseButtonEventArgs e)
{
if (!_hasHadInitialFocus)
{
e.Handled = true;
EditCell();
}
}
private void EditCell()
{
if (!_hasHadInitialFocus)
{
if (dataGrid.Items.Count - 2 >= 0 && dataGrid.Columns.Count - 1 >= 0)
{
var dataGridCellInfo = new DataGridCellInfo(
dataGrid.Items[dataGrid.Items.Count - 2], dataGrid.Columns[dataGrid.Columns.Count - 1]);
dataGrid.SelectedCells.Clear();
dataGrid.SelectedCells.Add(dataGridCellInfo);
dataGrid.CurrentCell = dataGridCellInfo;
dataGrid.BeginEdit();
}
_hasHadInitialFocus = true;
}
}

Highlighting Text in WP7 Databound Listbox

I am attempting to highlight text in a databound ListBox and highlight matching strings exactly like the email application on Windows Phone 7.
The search button pulls up a Popup, and on the TextChanged event, I'm filtering from a master list and re-setting the DataContext:
private void txtSearch_TextChanged(object sender, TextChangedEventArgs e)
{
results = allContent.Where(
x => x.Content.Contains(txtSearch.Text)
).ToList();
DataContext = results;
}
That part works great. The problem is with highlighting the matched text. I've tried iterating over the ListBoxItems in various events (Loaded, ItemsChanged) but they're always empty.
Any ideas about how text highlighting might be done in a databound ListItem's child TextBox?
Here is the solution that I went with:
private void ResultsText_Loaded(object sender, RoutedEventArgs e)
{
var textBlock = sender as TextBlock;
if (txtSearch.Text.Length > 0 && textBlock.Text.Length > 0)
{
BoldText(ref textBlock, txtSearch.Text, Color.FromArgb(255, 254, 247, 71));
}
}
public static void BoldText(ref TextBlock tb, string partToBold, Color color)
{
string Text = tb.Text;
tb.Inlines.Clear();
Run r = new Run();
r.Text = Text.Substring(0, Text.IndexOf(partToBold));
tb.Inlines.Add(r);
r = new Run();
r.Text = partToBold;
r.FontWeight = FontWeights.Bold;
r.Foreground = new SolidColorBrush(color);
tb.Inlines.Add(r);
r = new Run();
r.Text = Text.Substring(Text.IndexOf(partToBold) + partToBold.Length, Text.Length - (Text.IndexOf(partToBold) + partToBold.Length));
tb.Inlines.Add(r);
}

Resources