Related
I want when the button in Pagination is clicked, the dropdown of the Combo Box is still opened, so I can see the result of the pagination in the items of the Combo Box and the dropdown closed when I selected item of Combo Box.
My problem is when I click the buttons in Pagination, the dropdown of the Combo Box closed, so I can't see the result of the pagination.
How to prevent dropdown of Combo Box collapse before item selected in C# Win Form?
CtechComboBoxPagination.cs
using static DiscountCard.View.CustomControl.CtechPagination;
namespace DiscountCard.View.CustomControl
{
public partial class CtechComboBoxPagination : ComboBox
{
public CtechPagination? Pagination { get; set; }
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
public CtechComboBoxPagination()
{
InitializeComponent();
DoubleBuffered = true;
DropDownStyle = ComboBoxStyle.DropDownList;
DrawMode = DrawMode.OwnerDrawFixed;
Font = new Font("Consolas", 11F, FontStyle.Regular, GraphicsUnit.Point);
Pagination = new CtechPagination();
Pagination.SetInitialize(Enumerable.Range(0, 100).AsQueryable(), newContent: true, PaginationPosition.LastPage);
Pagination.FirstPaginationButton_Click += Pagination_FirstPaginationButton_Click;
Pagination.PrevPaginationButton_Click += Pagination_PrevPaginationButton_Click;
Pagination.NextPaginationButton_Click += Pagination_NextPaginationButton_Click;
Pagination.LastPaginationButton_Click += Pagination_LastPaginationButton_Click;
}
private void Pagination_FirstPaginationButton_Click(object? sender, EventArgs e)
{
DroppedDown = true;
}
private void Pagination_PrevPaginationButton_Click(object? sender, EventArgs e)
{
DroppedDown = true;
}
private void Pagination_NextPaginationButton_Click(object? sender, EventArgs e)
{
DroppedDown = true;
}
private void Pagination_LastPaginationButton_Click(object? sender, EventArgs e)
{
DroppedDown = true;
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
e.DrawBackground();
if (e.Index < 0 || e.Index >= Items.Count)
{
return;
}
var item = Items[e.Index];
String? text = item == null ? "(null)" : item.ToString();
TextRenderer.DrawText(e.Graphics, text, e.Font, e.Bounds, e.ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
base.OnDrawItem(e);
}
protected override void OnDropDown(EventArgs e)
{
base.OnDropDown(e);
if (Pagination == null)
{
return;
}
// for test
if (Pagination.CurrentPage != null)
{
Items.Clear();
for (int i = Pagination.CurrentPage.MinIndex; i <= Pagination.CurrentPage.MaxIndex; i++)
{
Items.Add(i);
}
}
Pagination.Margin = new Padding(0);
Pagination.MinimumSize = new Size(this.Width, 30);
ToolStripControlHost host = new ToolStripControlHost(Pagination);
host.Padding = new Padding(0);
ToolStripDropDown dropdown = new ToolStripDropDown();
dropdown.Padding = new Padding(0);
dropdown.Items.Add(host);
if (this.Items.Count > 0)
{
dropdown.Show(this, 0, 3 + this.Height + (this.Items.Count * this.ItemHeight));
}
}
}
}
CtechPagination.cs
using CardData.Ext.Mod.Logger;
using DiscountCard.Ext.Mod.General;
using DiscountCard.View.CustomControl.Pagination;
namespace DiscountCard.View.CustomControl
{
public partial class CtechPagination : UserControl
{
public enum PaginationPosition
{
FirstPage,
PreviousPage,
NextPage,
LastPage,
CurrrentPage
}
public CtechPagination()
{
InitializeComponent();
FirstPaginationButton.Click += OnFirstPaginationButton_Click;
PrevPaginationButton.Click += OnPrevPaginationButton_Click;
NextPaginationButton.Click += OnNextPaginationButton_Click;
LastPaginationButton.Click += OnLastPaginationButton_Click;
}
public event EventHandler? FirstPaginationButton_Click;
public event EventHandler? PrevPaginationButton_Click;
public event EventHandler? NextPaginationButton_Click;
public event EventHandler? LastPaginationButton_Click;
protected virtual void OnFirstPaginationButton_Click(object? sender, EventArgs e)
{
try
{
if (Pages == null)
{
return;
}
if (Pages.Count == 0)
{
return;
}
PageIndex = 0;
Page? firstPage = Pages[PageIndex];
if (firstPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", firstPage.MinIndex, firstPage.MaxIndex);
FirstPage = firstPage;
CurrentPage = firstPage;
FirstPaginationButton_Click?.Invoke(this, e);
}
}
catch (Exception ex)
{
ExLogger.LogException(ex, "");
}
}
protected virtual void OnPrevPaginationButton_Click(object? sender, EventArgs e)
{
try
{
if (Pages == null)
{
return;
}
if (Pages.Count == 0)
{
return;
}
--PageIndex;
if (PageIndex < 0)
{
PageIndex = 0;
}
Page? prevPage = Pages[PageIndex];
if (prevPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", prevPage.MinIndex, prevPage.MaxIndex);
PreviousPage = prevPage;
CurrentPage = prevPage;
PrevPaginationButton_Click?.Invoke(this, e);
}
}
catch (Exception ex)
{
ExLogger.LogException(ex, "");
}
}
protected virtual void OnNextPaginationButton_Click(object? sender, EventArgs e)
{
try
{
if (Pages == null)
{
return;
}
if (Pages.Count == 0)
{
return;
}
++PageIndex;
if (PageIndex > Pages.Count - 1)
{
PageIndex = Pages.Count - 1;
}
Page? nextPage = Pages[PageIndex];
if (nextPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", nextPage.MinIndex, nextPage.MaxIndex);
NextPage = nextPage;
CurrentPage = nextPage;
NextPaginationButton_Click?.Invoke(this, e);
}
}
catch (Exception ex)
{
ExLogger.LogException(ex, "");
}
}
protected virtual void OnLastPaginationButton_Click(object? sender, EventArgs e)
{
try
{
if (Pages == null)
{
return;
}
if (Pages.Count == 0)
{
return;
}
PageIndex = Pages.Count - 1;
Page? lastPage = Pages[PageIndex];
if (lastPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", lastPage.MinIndex, lastPage.MaxIndex);
LastPage = lastPage;
CurrentPage = lastPage;
LastPaginationButton_Click?.Invoke(this, e);
}
}
catch (Exception ex)
{
ExLogger.LogException(ex, "");
}
}
public void SetInitialize(IQueryable<int> source, bool newContent, PaginationPosition selectedPagination)
{
PageSize = Common.DEFAULT_PAGE_SIZE;
TotalCount = source.Count();
if (TotalCount <= 0)
{
return;
}
TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
if (TotalPages <= 0)
{
return;
}
if (newContent)
{
Pages = new List<Page>();
for (int i = 0; i < TotalPages; i++)
{
IQueryable<int> indexes = (IQueryable<int>)source.Skip(i * PageSize).Take(PageSize);
if (indexes != null)
{
Page page = new Page();
page.MinIndex = 1 + indexes.Min();
page.MaxIndex = 1 + indexes.Max();
Pages.Add(page);
}
}
}
if (Pages != null)
{
switch (selectedPagination)
{
case PaginationPosition.FirstPage:
if (newContent)
{
PageIndex = 0;
}
Page? firstPage = Pages[PageIndex];
if (firstPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", firstPage.MinIndex, firstPage.MaxIndex);
FirstPage = firstPage;
CurrentPage = firstPage;
}
break;
case PaginationPosition.PreviousPage:
if (newContent)
{
--PageIndex;
}
if (PageIndex < 0)
{
PageIndex = 0;
}
Page? prevPage = Pages[PageIndex];
if (prevPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", prevPage.MinIndex, prevPage.MaxIndex);
PreviousPage = prevPage;
CurrentPage = prevPage;
}
break;
case PaginationPosition.NextPage:
if (newContent)
{
++PageIndex;
}
if (PageIndex > Pages.Count - 1)
{
PageIndex = Pages.Count - 1;
}
Page? nextPage = Pages[PageIndex];
if (nextPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", nextPage.MinIndex, nextPage.MaxIndex);
NextPage = nextPage;
CurrentPage = nextPage;
}
break;
case PaginationPosition.LastPage:
if (newContent)
{
PageIndex = Pages.Count - 1;
}
if (PageIndex < 0)
{
PageIndex = 0;
}
Page? lastPage = Pages[PageIndex];
if (lastPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", lastPage.MinIndex, lastPage.MaxIndex);
LastPage = lastPage;
CurrentPage = lastPage;
}
break;
case PaginationPosition.CurrrentPage:
if (PageIndex < 0)
{
PageIndex = 0;
}
if (PageIndex > Pages.Count - 1)
{
PageIndex = Pages.Count - 1;
}
Page? curentPage = Pages[PageIndex];
if (curentPage != null)
{
PagesLabel.Text = String.Format("{0:N0} of {1:N0}", curentPage.MinIndex, curentPage.MaxIndex);
CurrentPage = curentPage;
}
break;
}
}
}
public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public int TotalPages { get; private set; }
public List<Page>? Pages { get; private set; }
public Page? CurrentPage { get; private set; }
public Page? FirstPage { get; private set; }
public Page? PreviousPage { get; private set; }
public Page? NextPage { get; private set; }
public Page? LastPage { get; private set; }
}
}
CtechPagination.Designer.cs
namespace DiscountCard.View.CustomControl
{
partial class CtechPagination
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.PaginationTableLayoutPanel = new DiscountCard.View.CustomControl.CtechTableLayoutPanel();
this.FirstPaginationButton = new System.Windows.Forms.Button();
this.PrevPaginationButton = new System.Windows.Forms.Button();
this.NextPaginationButton = new System.Windows.Forms.Button();
this.LastPaginationButton = new System.Windows.Forms.Button();
this.PagesLabel = new System.Windows.Forms.Label();
this.PaginationTableLayoutPanel.SuspendLayout();
this.SuspendLayout();
//
// PaginationTableLayoutPanel
//
this.PaginationTableLayoutPanel.ColumnCount = 9;
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 5F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 50F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 5F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 50F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 50F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 5F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 50F));
this.PaginationTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 5F));
this.PaginationTableLayoutPanel.Controls.Add(this.FirstPaginationButton, 1, 0);
this.PaginationTableLayoutPanel.Controls.Add(this.PrevPaginationButton, 3, 0);
this.PaginationTableLayoutPanel.Controls.Add(this.NextPaginationButton, 5, 0);
this.PaginationTableLayoutPanel.Controls.Add(this.LastPaginationButton, 7, 0);
this.PaginationTableLayoutPanel.Controls.Add(this.PagesLabel, 4, 0);
this.PaginationTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.PaginationTableLayoutPanel.Location = new System.Drawing.Point(0, 0);
this.PaginationTableLayoutPanel.Name = "PaginationTableLayoutPanel";
this.PaginationTableLayoutPanel.RowCount = 1;
this.PaginationTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.PaginationTableLayoutPanel.Size = new System.Drawing.Size(816, 30);
this.PaginationTableLayoutPanel.TabIndex = 0;
//
// FirstPaginationButton
//
this.FirstPaginationButton.Dock = System.Windows.Forms.DockStyle.Fill;
this.FirstPaginationButton.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FirstPaginationButton.Location = new System.Drawing.Point(8, 3);
this.FirstPaginationButton.Name = "FirstPaginationButton";
this.FirstPaginationButton.Size = new System.Drawing.Size(44, 24);
this.FirstPaginationButton.TabIndex = 0;
this.FirstPaginationButton.Text = "⟨⟨";
this.FirstPaginationButton.UseVisualStyleBackColor = true;
//
// PrevPaginationButton
//
this.PrevPaginationButton.Dock = System.Windows.Forms.DockStyle.Fill;
this.PrevPaginationButton.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.PrevPaginationButton.Location = new System.Drawing.Point(63, 3);
this.PrevPaginationButton.Name = "PrevPaginationButton";
this.PrevPaginationButton.Size = new System.Drawing.Size(44, 24);
this.PrevPaginationButton.TabIndex = 1;
this.PrevPaginationButton.Text = "⟨";
this.PrevPaginationButton.UseVisualStyleBackColor = true;
//
// NextPaginationButton
//
this.NextPaginationButton.Dock = System.Windows.Forms.DockStyle.Fill;
this.NextPaginationButton.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.NextPaginationButton.Location = new System.Drawing.Point(709, 3);
this.NextPaginationButton.Name = "NextPaginationButton";
this.NextPaginationButton.Size = new System.Drawing.Size(44, 24);
this.NextPaginationButton.TabIndex = 2;
this.NextPaginationButton.Text = "⟩";
this.NextPaginationButton.UseVisualStyleBackColor = true;
//
// LastPaginationButton
//
this.LastPaginationButton.Dock = System.Windows.Forms.DockStyle.Fill;
this.LastPaginationButton.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.LastPaginationButton.Location = new System.Drawing.Point(764, 3);
this.LastPaginationButton.Name = "LastPaginationButton";
this.LastPaginationButton.Size = new System.Drawing.Size(44, 24);
this.LastPaginationButton.TabIndex = 3;
this.LastPaginationButton.Text = "⟩⟩";
this.LastPaginationButton.UseVisualStyleBackColor = true;
//
// PagesLabel
//
this.PagesLabel.AutoSize = true;
this.PagesLabel.Dock = System.Windows.Forms.DockStyle.Fill;
this.PagesLabel.Location = new System.Drawing.Point(113, 0);
this.PagesLabel.Name = "PagesLabel";
this.PagesLabel.Size = new System.Drawing.Size(590, 30);
this.PagesLabel.TabIndex = 4;
this.PagesLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// CtechPagination
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.PaginationTableLayoutPanel);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "CtechPagination";
this.Size = new System.Drawing.Size(816, 30);
this.PaginationTableLayoutPanel.ResumeLayout(false);
this.PaginationTableLayoutPanel.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private CtechTableLayoutPanel PaginationTableLayoutPanel;
private Button FirstPaginationButton;
private Button PrevPaginationButton;
private Button NextPaginationButton;
private Button LastPaginationButton;
private Label PagesLabel;
}
}
As I understand it, you've made a UserControl for the pagination and when you click on one of the nav buttons it results in an unwanted close of the drop down.
I was able to reproduce the behavior you're describing and then was able to suppress it by implementing IMessageFilter for the user control in order to intercept the mouse events and mark them as "handled" in the filter (if they occur inside the client rectangle of the UC).
public partial class Pagination : UserControl, IMessageFilter
{
public Pagination()
{
InitializeComponent();
Application.AddMessageFilter(this);
Disposed += (sender, e) =>Application.RemoveMessageFilter(this);
PagesLabel.Text = $"Page {Page} of {Pages}";
}
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
public bool PreFilterMessage(ref Message m)
{
var client = PointToClient(MousePosition);
switch (m.Msg)
{
case WM_LBUTTONDOWN:
if (ClientRectangle.Contains(client))
{
IterateControlTree((control) => hitTest(control, client));
return true;
}
break;
case WM_LBUTTONUP:
if(ClientRectangle.Contains(client))
{
return true;
}
break;
}
return false;
}
.
.
.
}
To be clear, this means no Button.Click events are going to take place either! For this reason it's necessary to iterate the Control tree of the user control to perform a hit test on the button controls it contains.
bool IterateControlTree(Func<Control, bool> action, Control control = null)
{
if (control == null) control = this;
if(action(control)) return true;
foreach (Control child in control.Controls)
{
if(IterateControlTree(action, child))
{
return true;
}
}
return false;
}
For example, detecting a click in the client rectangle of one of the buttons could modify a Page property which in turn fires an event for the combo box to react.
private bool hitTest(Control control, Point client)
{
if (control.Bounds.Contains(client))
{
switch (control.Name)
{
case nameof(FirstPaginationButton): Page = 1; return true;
case nameof(PrevPaginationButton): Page --; return true;
case nameof(NextPaginationButton): Page ++; return true;
case nameof(LastPaginationButton): Page = Pages; return true;
default: break;
}
}
return false;
}
Feel free to browse or clone the code I wrote to test this answer if that would be helpful.
I have been tasked with creating a somewhat hierarchical datagridview for my company. I heavily modified one from Syed Shanu that is posted here https://www.codeproject.com/Articles/848637/Nested-DataGridView-in-windows-forms-csharp. I'm almost done (data loads properly, etc.), however I cannot for the life of me figure out how to get the detail grid to move when I scroll. It's a drawn on rectangle and I'm looking for a way to somehow bind it to the master grid so it scrolls up and down with the regular grid. Any help would be appreciated. Here is the code that draws the rectangle:
private void masterDGVs_CellContentClick_Event(object sender, DataGridViewCellEventArgs e)
{
DataGridViewImageColumn cols = (DataGridViewImageColumn)MasterDGVs.Columns[0];
MasterDGVs.Rows[e.RowIndex].Cells[0].Value = Image.FromFile(#"expand.png");
if (e.ColumnIndex == gridColumnIndex)
{
if (ImageName == #"expand.png")
{
DetailDGVs.Visible = true;
ImageName = #"toggle.png";
MasterDGVs.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Image.FromFile(ImageName);
String FilterExpression = MasterDGVs.Rows[e.RowIndex].Cells[FilterColumnName].Value.ToString();
MasterDGVs.Controls.Add(DetailDGVs);
Rectangle DGVRectangle = MasterDGVs.GetCellDisplayRectangle(1, e.RowIndex, true);
DetailDGVs.Size = new Size(MasterDGVs.Width - 48, DetailDGVs.PreferredSize.Height - 16);
DetailDGVs.Location = new Point(DGVRectangle.X, DGVRectangle.Y + 20);
DataView detailView = new DataView(DetailGridDT);
detailView.RowFilter = FilterColumnName + " = '" + FilterExpression + "'";
foreach (DataGridViewRow row in DetailDGVs.Rows)
{
if (row.Cells[5].Value.ToString() == "Error")
{
row.Cells[5].Style.ForeColor = Color.DarkRed;
}
else if (row.Cells[5].Value.ToString() == "Processed and Complete")
{
row.Cells[5].Style.ForeColor = Color.Green;
}
else
{
row.Cells[5].Style.ForeColor = Color.Yellow;
}
}
}
else
{
ImageName = #"expand.png";
MasterDGVs.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Image.FromFile(ImageName);
DetailDGVs.Visible = false;
}
}
else
{
DetailDGVs.Visible = false;
}
}
I have sort of working by adding:
MasterDGVs.MouseWheel += new MouseEventHandler(DetailDGV_Scroll);
DetailDGVs.MouseWheel += new MouseEventHandler(MasterDGV_Scroll);
and
private void DetailDGV_Scroll(object sender, MouseEventArgs e)
{
int scale = e.Delta * SystemInformation.MouseWheelScrollLines / 5;
DetailDGVs.Top = DetailDGVs.Top + scale;
}
private void MasterDGV_Scroll(object sender, MouseEventArgs e)
{
int scale = e.Delta * SystemInformation.MouseWheelScrollDelta / 5;
MasterDGVs.Top = MasterDGVs.Top - scale;
}
I have a route/polygon named "BBB"(figure1,figure2) in my GMap .Net Windows form Application.I am drawing route/polygon from mouse and storing all latitudes and longitudes into List<PointLatLng>.What i want is set of Latitudes and Longitudes between two intersecting points(latitude and longitude).
Note:
I have all Latitudes and Longitudes of route/polygon "BBB"(figure1,figure2) as well as "CCC"(figure1,figure2).
please let me know if something is not clear.Is there any Library or Api ?
Code: Some Code for Idea
List<PointLatLng> ListOfDragLatLang = new List<PointLatLng>();
PointLatLng StartingLatLng = new PointLatLng();
PointLatLng EndingLatLng = new PointLatLng();
// polygons
GMapPolygon polygon;
readonly GMapOverlay top = new GMapOverlay();
internal readonly GMapOverlay objects = new GMapOverlay("objects");//for storing markers
internal readonly GMapOverlay routes = new GMapOverlay("routes");// for storing routes
internal readonly GMapOverlay polygons = new GMapOverlay("polygons");//for storing polygons
public bool IsErasorCursorVisible { get => _IsErasorCursorVisible; set => _IsErasorCursorVisible = value; }
public bool IsPencilCursorVisible { get => _IsPencilCursorVisible; set => _IsPencilCursorVisible = value; }
public bool IsNormalCursorVisible { get => _IsNormalCursorVisible; set => _IsNormalCursorVisible = value; }
private void MainMap_MouseUp(object sender, MouseEventArgs e)
{
PointLatLng OnMouse = MainMap.FromLocalToLatLng(e.X, e.Y);
lblLatitude.Text = OnMouse.Lat.ToString();
lblLongitude.Text = OnMouse.Lng.ToString();
if (IsPencilCursorVisible && IsDrawing)
{
EndingLatLng = MainMap.FromLocalToLatLng(e.X, e.Y);
ListOfDragLatLang.Add(StartingLatLng);
IsDragging = false;
IsDrawing = false;
MainMap.DragButton = MouseButtons.Right;
//polygon = new GMapPolygon(ListOfDragLatLang, txtZoneName.Text);
//polygon.LocalPoints.AddRange(ListOfPoints);
//polygon.Stroke = new Pen(Color.Black, 3);
//polygon.IsHitTestVisible = true;
//polygon.Stroke.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
//polygons.Polygons.Add(polygon);
//MainMap.UpdatePolygonLocalPosition(polygon);
lblTotalPolygonsAdded.Text = polygons.Polygons.Count.ToString();
for (int i = 0; i < ListOfDragLatLang.Count; i++)
{
AddPinPointToPolygon(ListOfDragLatLang[i], i, txtZoneName.Text);
}
RegenerateRoute(txtZoneName.Text);
GMarkerGoogle marker = new GMarkerGoogle(new PointLatLng(ListOfDragLatLang.Sum(c => c.Lat) / ListOfDragLatLang.Count, ListOfDragLatLang.Sum(c => c.Lng) / ListOfDragLatLang.Count), GMarkerGoogleType.orange_dot);
marker.ToolTip = new GMapBaloonToolTip(marker);
marker.ToolTipText = txtZoneName.Text;
marker.ToolTipMode = MarkerTooltipMode.Always;
marker.IsVisible = true;
marker.Tag = txtZoneName.Text;
objects.Markers.Add(marker);
MainMap.UpdateMarkerLocalPosition(marker);
MainMap.UpdatePolygonLocalPosition(polygon);
}
}
private void MainMap_MouseDown(object sender, MouseEventArgs e)
{
PointLatLng OnMouse = MainMap.FromLocalToLatLng(e.X, e.Y);
if (e.Button == MouseButtons.Left)
{
if (IsPencilCursorVisible && IsDrawing)
{
StartingLatLng = OnMouse;
ListOfDragLatLang.Add(StartingLatLng);
ListOfPoints.Add(new GPoint(e.X, e.Y));
IsDragging = true;
MainMap.DragButton = MouseButtons.Middle;
currentRoute = new GMapRoute(txtZoneName.Text);
currentRoute.Stroke = new Pen(Color.Black, 3);
currentRoute.IsHitTestVisible = true;
routes.Routes.Add(currentRoute);
MainMap.UpdateRouteLocalPosition(currentRoute);
//polygon = new GMapPolygon(ListOfDragLatLang,txtZoneName.Text);
//polygon.LocalPoints.AddRange(ListOfPoints);
//polygon.Stroke = new Pen(Color.Black, 3);
//polygon.IsHitTestVisible = true;
//polygon.Stroke.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
//polygons.Polygons.Add(polygon);
//MainMap.UpdatePolygonLocalPosition(polygon);
}
}
}
private void MainMap_MouseMove(object sender, MouseEventArgs e)
{
PointLatLng OnMouse = MainMap.FromLocalToLatLng(e.X, e.Y);
lblLatitude.Text = OnMouse.Lat.ToString();
lblLongitude.Text = OnMouse.Lng.ToString();
if (e.Button == MouseButtons.Left)
{
if (IsPencilCursorVisible && IsDrawing)
{
if (MainMap.IsMouseOverPolygon)
{
MainMap.Cursor = MainCursor;
}
else
{
MainMap.Cursor = PencilCursor;
}
IsDragging = true;
ListOfPoints.Add(new GPoint(e.X, e.Y));
ListOfDragLatLang.Add(OnMouse);
lblTotalLatLng.Text = ListOfDragLatLang.Count.ToString();
currentRoute.Points.Add(OnMouse);
MainMap.UpdateRouteLocalPosition(currentRoute);
//polygon.Points.Add(OnMouse);
//MainMap.UpdatePolygonLocalPosition(polygon);
}
else
{
PointLatLng pnew = MainMap.FromLocalToLatLng(e.X, e.Y);
if (CurentRectMarker == null)
{
return;
}
int? pIndex = (int?)CurentRectMarker.Tag;
if (pIndex.HasValue)
{
if (pIndex < currentRoute.Points.Count)
{
currentRoute.Points[pIndex.Value] = pnew;
MainMap.UpdateRouteLocalPosition(currentRoute);
}
//if (pIndex < polygon.Points.Count)
//{
// polygon.Points[pIndex.Value] = pnew;
// MainMap.UpdatePolygonLocalPosition(polygon);
//}
}
if (currentMarker.IsVisible)
{
currentMarker.Position = pnew;
}
CurentRectMarker.Position = pnew;
if (CurentRectMarker.InnerMarker != null)
{
CurentRectMarker.InnerMarker.Position = pnew;
}
}
MainMap.Refresh();
}
}
Figure 1
Figure 2
Question:How to get the Latitudes and Longitudes of yellow color edge in figure 2 between intersecting point "A" and "B"?
Assuming your List is in the correct order
Find the index of the coordinate at point A and B in your List and then create a new list using all points that are between the two indexes.
I've a txt file with a 360 numbers, I must read all of these and draw a kind of Disc made of FillPie eachone colored in scale of grey due to the value of the list. Until here everything is quite simple.I made a class with the data(value in the txt and degree) of one single fillpie with a Paint method that draw it of the correct color.
this is the code of the class:
class DatoDisco
{
int valoreSpicchio;
int gradi;
public DatoDisco(int valoreTastatore, int gradiLettura)
{
valoreSpicchio = valoreTastatore;
gradi = gradiLettura;
}
public void Clear()
{
valoreSpicchio = 0;
gradi = 0;
}
private int ScalaGrigi()
{
int grigio = 0;
if (valoreSpicchio <= 0)
{
grigio = 125 + (valoreSpicchio / 10);
if (grigio < 0)
grigio = 0;
}
if (valoreSpicchio > 0)
{
grigio = 125 + (valoreSpicchio / 10);
if (grigio > 230)
grigio = 230;
}
return grigio;
}
public void Paint (Graphics grafica)
{
try
{
Brush penna = new SolidBrush(Color.FromArgb(255, ScalaGrigi(), ScalaGrigi(), ScalaGrigi()));
grafica.FillPie(penna, 0, 0, 400, 400, gradi, 1.0f);
}
catch
{
}
}
public int ValoreSpicchio
{
get
{
return valoreSpicchio;
}
}
public int Gradi
{
get
{
return gradi;
}
}
}
here is where I draw everything:
public partial class Samac : Form
{
libnodave.daveOSserialType fds;
libnodave.daveInterface di;
libnodave.daveConnection dc;
int rack = 0;
int slot = 2;
int scalaGrigi = 0;
int angolatura = 0;
List<int> valoriY = new List<int>();
//Disco disco = new Disco();
List<DatoDisco> disco = new List<DatoDisco>();
float[] valoriTastatore = new float[360];
public Samac()
{
InitializeComponent();
StreamReader dataStream = new StreamReader("save.txt");
textBox1.Text = dataStream.ReadLine();
dataStream.Dispose();
for (int i = 0; i <= 360; i++ )
chart1.Series["Series2"].Points.Add(0);
//AggiornaGrafico(textBox1.Text, chart1);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
string indirizzoIpPlc
{
get
{
FileIniDataParser parser = new FileIniDataParser();
IniData settings = parser.LoadFile("config.ini");
return settings["PLC_CONNECTION"]["PLC_IP"];
}
}
private void AggiornaGrafico(string nomeFile, Chart grafico, bool online)
{
int max = 0;
int min = 0;
grafico.Series["Series1"].Points.Clear();
grafico.Series["Series2"].Points.Clear();
grafico.Series["Series3"].Points.Clear();
grafico.Series["Series4"].Points.Clear();
grafico.ChartAreas[0].AxisX.Maximum = 360;
grafico.ChartAreas[0].AxisX.Minimum = 0;
grafico.ChartAreas[0].AxisY.Maximum = 500;
grafico.ChartAreas[0].AxisY.Minimum = -500;
String file = nomeFile;
valoriY.Clear();
disco.Clear();
if (online == false)
{
System.IO.File.WriteAllText("save.txt", nomeFile);
}
StreamReader dataStreamGrafico = new StreamReader(file);
StreamReader dataStreamScheda = new StreamReader("Scheda.sch");
string datasample;
string[] scheda = new string[56];
for (int i = 0; i < 56; i++)
{
scheda[i] = dataStreamScheda.ReadLine();
}
dataStreamScheda.Close();
int gradi = 1;
while ((datasample = dataStreamGrafico.ReadLine()) != null)
{
grafico.Series["Series2"].Points.Add(0);
grafico.Series["Series2"].Color = Color.Red;
grafico.Series["Series2"].BorderWidth = 3;
grafico.Series["Series3"].Points.Add(Convert.ToInt32(float.Parse(scheda[5])));
grafico.Series["Series3"].Color = Color.Green;
grafico.Series["Series3"].BorderWidth = 3;
grafico.Series["Series4"].Points.Add(Convert.ToInt32(-float.Parse(scheda[5])));
grafico.Series["Series4"].Color = Color.Green;
grafico.Series["Series4"].BorderWidth = 3;
grafico.Series["Series1"].Points.Add(int.Parse(datasample));
grafico.Series["Series1"].BorderWidth = 5;
valoriY.Add(int.Parse(datasample));
//disco.Add(int.Parse(datasample));
disco.Add(new DatoDisco(int.Parse(datasample), gradi));
gradi++;
}
dataStreamGrafico.Close();
max = Convert.ToInt32(chart1.Series["Series1"].Points.FindMaxByValue().YValues[0]);
min = Convert.ToInt32(chart1.Series["Series1"].Points.FindMinByValue().YValues[0]);
lblCampanatura.Text = (((float)max + min) / 2000.0).ToString();
lblSbandieramento.Text = (((float)max - min) / 1000.0).ToString();
if ((Math.Abs(max) > 800) || (Math.Abs(min) > 800))
{
if (Math.Abs(max) >= Math.Abs(min))
{
chart1.ChartAreas[0].AxisY.Maximum = max + 200;
chart1.ChartAreas[0].AxisY.Minimum = -(max + 200);
}
else
{
chart1.ChartAreas[0].AxisY.Maximum = min + 200;
chart1.ChartAreas[0].AxisY.Minimum = -(min + 200);
}
}
else
{
chart1.ChartAreas[0].AxisY.Maximum = 800;
chart1.ChartAreas[0].AxisY.Minimum = -800;
}
boxGraficaDisco.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog1.ShowDialog();
textBox1.Text = openFileDialog1.FileName;
if (result == DialogResult.OK)
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
}
ToolTip tooltip = new ToolTip();
private int lastX;
private int lastY;
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
if (e.X != this.lastX || e.Y != this.lastY)
{
try
{
int cursorX = Convert.ToInt32(chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.Location.X));
tooltip.Show("X:" + cursorX.ToString("0.00") + "Y:" + Convert.ToInt32(chart1.Series[0].Points[cursorX].YValues[0]).ToString(), this.chart1, e.Location.X + 20, e.Location.Y + 20);
}
catch { }
}
this.lastX = e.X;
this.lastY = e.Y;
}
private void button1_Click_1(object sender, EventArgs e)
{
int indice = ((int)Char.GetNumericValue(textBox1.Text[textBox1.Text.Length - 5]))+1;
if (File.Exists(textBox1.Text.Substring(0, textBox1.Text.Length - 5) + indice + ".txt"))
{
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 5) + indice + ".txt";
try
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
catch
{
MessageBox.Show("Il File non esiste");
}
}
else
{
MessageBox.Show("Il File non esiste");
}
}
private void btnGrafMeno_Click(object sender, EventArgs e)
{
int indice = ((int)Char.GetNumericValue(textBox1.Text[textBox1.Text.Length - 5])) - 1;
if (indice >= 0)
{
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 5) + indice + ".txt";
try
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
catch
{
MessageBox.Show("Il File non esiste");
}
}
else
{
MessageBox.Show("Prima lettura disco");
}
}
private void btnConnetti_Click(object sender, EventArgs e)
{
fds.rfd = libnodave.openSocket(102, indirizzoIpPlc);
fds.wfd = fds.rfd;
if (fds.rfd > 0)
{
di = new libnodave.daveInterface(fds, "IF1", 0, libnodave.daveProtoISOTCP, libnodave.daveSpeed187k);
di.setTimeout(1000000);
dc = new libnodave.daveConnection(di, 0, rack, slot);
int res = dc.connectPLC();
timer1.Start();
// AggiornaGrafico("Disco.csv", chart1, timer1.Enabled);
}
else
{
MessageBox.Show("Impossibile connettersi");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
int res;
res = dc.readBytes(libnodave.daveDB, 21, 40, 1, null);
if (res == 0)
{
var letturaDati = (dc.getS8At(0) & (1 << 0)) != 0;
if (letturaDati == true)
{
int puntatore = 30;
StreamWriter datiDisco = new StreamWriter("DatiDaPlc.csv");
datiDisco.WriteLine("X;" + "C;" + "Z;");
while (puntatore <= 10838)
{
res = dc.readBytes(libnodave.daveDB, 3, puntatore, 192, null);
if (res == 0)
{
for (int i = 0; dc.getU32At(i) != 0; i = i + 12)
{
datiDisco.Write(dc.getU32At(i).ToString() + ";");
datiDisco.Write(dc.getU32At(i + 4).ToString() + ";");
datiDisco.WriteLine(dc.getFloatAt(i + 8).ToString() + ";");
}
}
puntatore = puntatore + 192;
}
datiDisco.Close();
StreamReader lettura = new StreamReader("DatiDaPlc.csv");
StreamWriter scritt = new StreamWriter("Disco.csv");
var titolo = lettura.ReadLine();
var posizioneLettura = lettura.ReadLine();
var posX = posizioneLettura.Split(';');
int minX = Convert.ToInt32(posX[0]) - 5;
int maxX = Convert.ToInt32(posX[0]) + 5;
int contatore = 0;
while (!lettura.EndOfStream)
{
var line = lettura.ReadLine();
var values = line.Split(';');
if ((Convert.ToInt32(values[1]) >= contatore && Convert.ToInt32(values[1]) < contatore + 1000) && (Convert.ToInt32(values[0]) > minX && Convert.ToInt32(values[0]) <= maxX))
{
scritt.WriteLine(Convert.ToInt32(float.Parse(values[2]) * 1000).ToString());
contatore += 1000;
}
}
lettura.Close();
scritt.Close();
AggiornaGrafico("Disco.csv", chart1, timer1.Enabled);
}
}
else
{
timer1.Stop();
MessageBox.Show("Disconnesso");
dc.disconnectPLC();
di.disconnectAdapter();
fds.rfd = libnodave.closeSocket(102);
fds.wfd = fds.rfd;
}
}
}
private void btnDisconnetti_Click(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
dc.disconnectPLC();
di.disconnectAdapter();
fds.rfd = libnodave.closeSocket(102);
fds.wfd = fds.rfd;
timer1.Stop();
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
}
private void Samac_FormClosing(object sender, FormClosingEventArgs e)
{
if (timer1.Enabled == true)
{
dc.disconnectPLC();
di.disconnectAdapter();
libnodave.closeSocket(102);
timer1.Stop();
}
}
private void button1_Click_2(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
AggiornaGrafico("Disco.csv", chart1, timer1.Enabled);
}
else
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
}
private void chart2_MouseMove(object sender, MouseEventArgs e)
{
if (e.X != this.lastX || e.Y != this.lastY)
{
try
{
int cursorX = Convert.ToInt32(chart2.ChartAreas[0].AxisX.PixelPositionToValue(e.Location.X));
int cursorY = Convert.ToInt32(chart2.ChartAreas[0].AxisY.PixelPositionToValue(e.Location.Y));
//tooltip.Show("X:" + chart2.Series[0].Points[cursorX].XValue.ToString() + "Y:" + chart2.Series[0].Points[cursorX].YValues[0].ToString(), this.chart2, e.Location.X + 20, e.Location.Y + 20);
tooltip.Show("X:" + cursorX.ToString() + "Y:#VALY" , this.chart2, e.Location.X + 20, e.Location.Y + 20);
//chart2.Series[0].ToolTip="#VALY";
}
catch { }
}
this.lastX = e.X;
this.lastY = e.Y;
}
private void boxGraficaDisco_Paint(object sender, PaintEventArgs e)
{
Graphics grafica = e.Graphics;
//disco.Paint(grafica);
foreach (DatoDisco d in disco)
{
d.Paint(grafica);
}
}
private void boxGraficaDisco_MouseMove(object sender, MouseEventArgs e)
{
if (e.X != this.lastX || e.Y != this.lastY)
{
try
{
foreach (DatoDisco d in disco)
{
}
}
catch { }
}
this.lastX = e.X;
this.lastY = e.Y;
}
}
Now I need that when i go with the mouse over the drawn disc, a tooltip show me the data of the fillPie(degree and value of txt) but i can't figure out how.
Anyone can help me?
this is an image of the disc
Eventually it looks as if all you want is a function to get the angle between the mouse position and the center of the disc..
Here is a function to calculate an angle given two points:
double AngleFromPoints(Point pt1, Point pt2)
{
Point P = new Point(pt1.X - pt2.X, pt1.Y - pt2.Y);
double alpha = 0d;
if (P.Y == 0) alpha = P.X > 0 ? 0d : 180d;
else
{
double f = 1d * P.X / (Math.Sqrt(P.X * P.X + P.Y * P.Y));
alpha = Math.Acos(f) * 180d / Math.PI;
if (P.Y > 0) alpha = 360d - alpha;
}
return alpha;
}
Actually I have solved the problem of having checkbox in the header of a DGV, here is the code
Rectangle rect = dataGridView1.GetCellDisplayRectangle(0, -1, true);
rect.Y = 3;
rect.X = rect.Location.X + (rect.Width/4);
CheckBox checkboxHeader = new CheckBox();
checkboxHeader.Name = "checkboxHeader";
//datagridview[0, 0].ToolTipText = "sdfsdf";
checkboxHeader.Size = new Size(18, 18);
checkboxHeader.Location = rect.Location;
checkboxHeader.CheckedChanged += new EventHandler(checkboxHeader_CheckedChanged);
dataGridView1.Controls.Add(checkboxHeader);
Actually First I add a column to my DGV which is a DataGridViewCheckBoxColumn and then in the load of the form adding the code above, my problem is as you can see below for the first column it works great since I can set the rect.X in the code for that column but what about the notifier column how can I know where is the position of the header of this column programmatically since the log column can change through maximizing and this stuffs.
Finally, How can I know for example what is the position of the header of the column[3] programatically....
Thanks in advance
try this
#region GridViewCheckBoxColumn
[System.Drawing.ToolboxBitmap(typeof(System.Windows.Forms.DataGridViewCheckBoxColumn))]
public class GridViewCheckBoxColumn : DataGridViewCheckBoxColumn
{
#region Constructor
public GridViewCheckBoxColumn()
{
DatagridViewCheckBoxHeaderCell datagridViewCheckBoxHeaderCell = new DatagridViewCheckBoxHeaderCell();
this.HeaderCell = datagridViewCheckBoxHeaderCell;
this.Width = 50;
//this.DataGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.grvList_CellFormatting);
datagridViewCheckBoxHeaderCell.OnCheckBoxClicked += new CheckBoxClickedHandler(datagridViewCheckBoxHeaderCell_OnCheckBoxClicked);
}
#endregion
#region Methods
void datagridViewCheckBoxHeaderCell_OnCheckBoxClicked(int columnIndex, bool state)
{
DataGridView.RefreshEdit();
foreach (DataGridViewRow row in this.DataGridView.Rows)
{
if (!row.Cells[columnIndex].ReadOnly)
{
row.Cells[columnIndex].Value = state;
}
}
DataGridView.RefreshEdit();
}
#endregion
}
#endregion
#region DatagridViewCheckBoxHeaderCell
public delegate void CheckBoxClickedHandler(int columnIndex, bool state);
public class DataGridViewCheckBoxHeaderCellEventArgs : EventArgs
{
bool _bChecked;
public DataGridViewCheckBoxHeaderCellEventArgs(int columnIndex, bool bChecked)
{
_bChecked = bChecked;
}
public bool Checked
{
get { return _bChecked; }
}
}
class DatagridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell
{
Point checkBoxLocation;
Size checkBoxSize;
bool _checked = false;
Point _cellLocation = new Point();
System.Windows.Forms.VisualStyles.CheckBoxState _cbState =
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
public event CheckBoxClickedHandler OnCheckBoxClicked;
public DatagridViewCheckBoxHeaderCell()
{
}
protected override void Paint(System.Drawing.Graphics graphics,
System.Drawing.Rectangle clipBounds,
System.Drawing.Rectangle cellBounds,
int rowIndex,
DataGridViewElementStates dataGridViewElementState,
object value,
object formattedValue,
string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts)
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex,
dataGridViewElementState, value,
formattedValue, errorText, cellStyle,
advancedBorderStyle, paintParts);
Point p = new Point();
Size s = CheckBoxRenderer.GetGlyphSize(graphics,
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
p.X = cellBounds.Location.X +
(cellBounds.Width / 2) - (s.Width / 2);
p.Y = cellBounds.Location.Y +
(cellBounds.Height / 2) - (s.Height / 2);
_cellLocation = cellBounds.Location;
checkBoxLocation = p;
checkBoxSize = s;
if (_checked)
_cbState = System.Windows.Forms.VisualStyles.
CheckBoxState.CheckedNormal;
else
_cbState = System.Windows.Forms.VisualStyles.
CheckBoxState.UncheckedNormal;
CheckBoxRenderer.DrawCheckBox
(graphics, checkBoxLocation, _cbState);
}
protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
{
Point p = new Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y);
if (p.X >= checkBoxLocation.X && p.X <=
checkBoxLocation.X + checkBoxSize.Width
&& p.Y >= checkBoxLocation.Y && p.Y <=
checkBoxLocation.Y + checkBoxSize.Height)
{
_checked = !_checked;
if (OnCheckBoxClicked != null)
{
OnCheckBoxClicked(e.ColumnIndex, _checked);
this.DataGridView.InvalidateCell(this);
}
}
base.OnMouseClick(e);
}
}
#endregion
#region ColumnSelection
class DataGridViewColumnSelector
{
// the DataGridView to which the DataGridViewColumnSelector is attached
private DataGridView mDataGridView = null;
// a CheckedListBox containing the column header text and checkboxes
private CheckedListBox mCheckedListBox;
// a ToolStripDropDown object used to show the popup
private ToolStripDropDown mPopup;
/// <summary>
/// The max height of the popup
/// </summary>
public int MaxHeight = 300;
/// <summary>
/// The width of the popup
/// </summary>
public int Width = 200;
/// <summary>
/// Gets or sets the DataGridView to which the DataGridViewColumnSelector is attached
/// </summary>
public DataGridView DataGridView
{
get { return mDataGridView; }
set
{
// If any, remove handler from current DataGridView
if (mDataGridView != null) mDataGridView.CellMouseClick -= new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick);
// Set the new DataGridView
mDataGridView = value;
// Attach CellMouseClick handler to DataGridView
if (mDataGridView != null) mDataGridView.CellMouseClick += new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick);
}
}
// When user right-clicks the cell origin, it clears and fill the CheckedListBox with
// columns header text. Then it shows the popup.
// In this way the CheckedListBox items are always refreshed to reflect changes occurred in
// DataGridView columns (column additions or name changes and so on).
void mDataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right && e.RowIndex == -1 && e.ColumnIndex == 0)
{
mCheckedListBox.Items.Clear();
foreach (DataGridViewColumn c in mDataGridView.Columns)
{
mCheckedListBox.Items.Add(c.HeaderText, c.Visible);
}
int PreferredHeight = (mCheckedListBox.Items.Count * 16) + 7;
mCheckedListBox.Height = (PreferredHeight < MaxHeight) ? PreferredHeight : MaxHeight;
mCheckedListBox.Width = this.Width;
mPopup.Show(mDataGridView.PointToScreen(new Point(e.X, e.Y)));
}
}
// The constructor creates an instance of CheckedListBox and ToolStripDropDown.
// the CheckedListBox is hosted by ToolStripControlHost, which in turn is
// added to ToolStripDropDown.
public DataGridViewColumnSelector()
{
mCheckedListBox = new CheckedListBox();
mCheckedListBox.CheckOnClick = true;
mCheckedListBox.ItemCheck += new ItemCheckEventHandler(mCheckedListBox_ItemCheck);
ToolStripControlHost mControlHost = new ToolStripControlHost(mCheckedListBox);
mControlHost.Padding = Padding.Empty;
mControlHost.Margin = Padding.Empty;
mControlHost.AutoSize = false;
mPopup = new ToolStripDropDown();
mPopup.Padding = Padding.Empty;
mPopup.Items.Add(mControlHost);
}
public DataGridViewColumnSelector(DataGridView dgv)
: this()
{
this.DataGridView = dgv;
}
// When user checks / unchecks a checkbox, the related column visibility is
// switched.
void mCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
mDataGridView.Columns[e.Index].Visible = (e.NewValue == CheckState.Checked);
}
}
#endregion
This solution works for me, it adds the checkbox to the header cell. You just have to implement the "check all" method and eventually a "on column resize" method (for replace checkbox in the center)
// Creating checkbox without panel
CheckBox checkbox = new CheckBox();
checkbox.Size = new System.Drawing.Size(15, 15);
checkbox.BackColor = Color.Transparent;
// Reset properties
checkbox.Padding = new Padding(0);
checkbox.Margin = new Padding(0);
checkbox.Text = "";
// Add checkbox to datagrid cell
myDataGrid.Controls.Add(checkbox);
DataGridViewHeaderCell header = myDataGrid.Columns[myColumnWithCheckboxes.Index].HeaderCell;
checkbox.Location = new Point(
header.ContentBounds.Left + (header.ContentBounds.Right - header.ContentBounds.Left + checkbox.Size.Width) / 2,
header.ContentBounds.Top + (header.ContentBounds.Bottom - header.ContentBounds.Top + checkbox.Size.Height) / 2
);
To me, cleanest solution is from "56ka" and this is my upgrade on it. With this, you retain an ability to sort and see the sort direction and to have a label next to the checkbox, normal checkbox and all it has to offer. Made on .NET Framework 4.0 for DataTable. Works with DataTable and EF.
public static void AddSelectorColumn(this DataGridView dgv, int width = 50, string columnName = "Selected", Action<DataGridViewColumn> addHeaderCheckBoxOverride = null)
{
if (dgv.Columns[columnName] == null)
{
var dt = dgv.Table();
var dcol = new DataColumn(columnName, typeof(bool));
dt.Columns.Add(dcol);
dt.ColumnChanged += (s, e) =>
{
var chCols = e.Row.GetChangedColumns();
if (chCols.Count == 1 && chCols[0].Equals(dcol))
e.Row.AcceptChanges();
};
}
var col = dgv.Columns[columnName];
col.HeaderText = "";
col.ReadOnly = false;
col.DisplayIndex = 0;
if (addHeaderCheckBoxOverride != null)
addHeaderCheckBoxOverride(col);
else
col.AddHeaderCheckBox();
col.Width = width;
}
public static CheckBox AddHeaderCheckBox(this DataGridViewColumn column, HorizontalAlignment align = HorizontalAlignment.Center, int leftBorderOffset = 0, int rightBorderOffset = 0, Func<object, bool> getValue = null, Action<object, bool> setValue = null)
{
if (column.DataGridView == null) throw new ArgumentNullException("First you need to add the column to grid.");
// Creating checkbox without panel
CheckBox checkbox = new CheckBox();
checkbox.Name = "chk" + column.Name;
checkbox.Size = new Size(15, 15);
checkbox.BackColor = Color.Transparent;
checkbox.Enabled = !column.ReadOnly;
// Reset properties
checkbox.Padding = new Padding(0);
checkbox.Margin = new Padding(0);
checkbox.Text = "";
var changedByUser = true;
var dgv = column.DataGridView;
checkbox.CheckedChanged += (s, e) =>
{
if (changedByUser)
{
try
{
changedByUser = false;
if (dgv.IsCurrentCellInEditMode && dgv.CurrentCell.OwningColumn.Name.Equals(column.Name))
dgv.EndEdit();
var dgvRows = new List<DataGridViewRow>((dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows).Cast<DataGridViewRow>());
if (column.IsDataBound)
{
//adding to list because of BindingSource sort by that column
var boundItems = new List<object>();
var areDataRows = dgvRows.Count < 1 || dgvRows[0].DataBoundItem is DataRowView;
if (areDataRows)
{
foreach (DataGridViewRow row in dgvRows)
boundItems.Add(((DataRowView)row.DataBoundItem).Row);
foreach (DataRow dr in boundItems)
{
var val = dr[column.DataPropertyName];
if ((val is bool && (bool)val) != checkbox.Checked)
dr[column.DataPropertyName] = checkbox.Checked;
}
}
else
{
foreach (DataGridViewRow row in dgvRows)
boundItems.Add(row.DataBoundItem);
foreach (var item in boundItems)
{
var val = getValue(item);
if (val != checkbox.Checked)
setValue(item, checkbox.Checked);
}
}
}
else
{
foreach (DataGridViewRow dgr in dgvRows)
{
var cell = dgr.Cells[column.Name];
if ((cell.Value is bool && (bool)cell.Value) != checkbox.Checked)
cell.Value = checkbox.Checked;
}
}
}
finally
{
changedByUser = true;
}
}
};
// Add checkbox to datagrid cell
dgv.Controls.Add(checkbox);
Action onColResize = () =>
{
var colCheck = dgv.Columns[column.Name];
if (colCheck == null) return;
int colLeft = (dgv.RowHeadersVisible ? dgv.RowHeadersWidth : 0) - (colCheck.Frozen ? 0 : dgv.HorizontalScrollingOffset);
foreach (DataGridViewColumn col in dgv.Columns)
{
if (col.DisplayIndex >= colCheck.DisplayIndex) break;
if (!col.Visible) continue;
colLeft += col.Width;
}
var newPoint = new Point(colLeft, dgv.ColumnHeadersHeight / 2 - checkbox.Height / 2);
if (align == HorizontalAlignment.Left)
newPoint.X += 3;
else if (align == HorizontalAlignment.Center)
newPoint.X += colCheck.Width / 2 - checkbox.Width / 2;
else if (align == HorizontalAlignment.Right)
newPoint.X += colCheck.Width - checkbox.Width - 3;
var minLeft = colLeft + leftBorderOffset;
var maxLeft = colLeft + colCheck.Width - checkbox.Width + rightBorderOffset;
if (newPoint.X < minLeft) newPoint.X = minLeft;
if (newPoint.X > maxLeft) newPoint.X = maxLeft;
checkbox.Location = newPoint;
checkbox.Visible = colCheck.Visible;
};
dgv.ColumnWidthChanged += (s, e) => onColResize();
dgv.ColumnHeadersHeightChanged += (s, e) => onColResize();
dgv.Scroll += (s, e) => onColResize();
dgv.Resize += (s, e) => onColResize();
dgv.Sorted += (s, e) => onColResize();
dgv.RowHeadersWidthChanged += (s, e) => onColResize();
dgv.ColumnStateChanged += (s, e) => onColResize();
Action<object> onDataChanged = (e) =>
{
if (!changedByUser) return;
if (e is DataColumnChangeEventArgs)
{
if (!((DataColumnChangeEventArgs)e).Column.ColumnName.Equals(column.Name))
return;
}
else if (e is ListChangedEventArgs)
{
var prop = ((ListChangedEventArgs)e).PropertyDescriptor;
if (prop != null && !prop.Name.Equals(column.DataPropertyName))
return;
}
bool allAreTrue = true;
foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows)
{
var val = row.Cells[column.Name].Value;
if (!(val is bool) || !(bool)val)
{
allAreTrue = false;
break;
}
}
try
{
changedByUser = false;
var tag = checkbox.Tag;
checkbox.Tag = "AUTO";
try
{
checkbox.Checked = allAreTrue;
}
finally { checkbox.Tag = tag; }
}
finally
{
changedByUser = true;
}
};
dgv.SelectionChanged += (s, e) => onDataChanged(e);
if (dgv.DataSource is BindingSource)
((BindingSource)dgv.DataSource).ListChanged += (s, e) => onDataChanged(e);
else if (dgv.DataSource is DataSet)
((DataSet)dgv.DataSource).Tables[dgv.DataMember].ColumnChanged += (s, e) => onDataChanged(e);
else if (dgv.DataSource is DataTable)
((DataTable)dgv.DataSource).ColumnChanged += (s, e) => onDataChanged(e);
return checkbox;
}
The Answer of 56ka is perfekt for me.
I just fix the location (2px)
private CheckBox ColumnCheckbox(DataGridView dataGridView)
{
CheckBox checkBox = new CheckBox();
checkBox.Size = new Size(15, 15);
checkBox.BackColor = Color.Transparent;
// Reset properties
checkBox.Padding = new Padding(0);
checkBox.Margin = new Padding(0);
checkBox.Text = "";
// Add checkbox to datagrid cell
dataGridView.Controls.Add(checkBox);
DataGridViewHeaderCell header = dataGridView.Columns[0].HeaderCell;
checkBox.Location = new Point(
(header.ContentBounds.Left +
(header.ContentBounds.Right - header.ContentBounds.Left + checkBox.Size.Width)
/2) - 2,
(header.ContentBounds.Top +
(header.ContentBounds.Bottom - header.ContentBounds.Top + checkBox.Size.Height)
/2) - 2);
return checkBox;
}
public class DataGridViewEx : DataGridView
{
Dictionary<DataGridViewColumn, bool> dictionaryCheckBox = new Dictionary<DataGridViewColumn, bool>();
System.Drawing.Bitmap[] bmCheckBox = new System.Drawing.Bitmap[2];
bool executarValueChanged = true;
public DataGridViewEx()
: base()
{
#region CheckBox no header da coluna
CheckBox chkTemp = new CheckBox();
chkTemp.AutoSize = true;
chkTemp.BackColor = System.Drawing.Color.Transparent;
chkTemp.Size = new System.Drawing.Size(16, 16);
chkTemp.UseVisualStyleBackColor = false;
bmCheckBox[0] = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);
bmCheckBox[1] = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);
chkTemp.Checked = false;
chkTemp.DrawToBitmap(bmCheckBox[0], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
chkTemp.Checked = true;
chkTemp.DrawToBitmap(bmCheckBox[1], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
#endregion
}
public void CheckBoxHeader(DataGridViewCheckBoxColumn column, bool enabled)
{
if (enabled == true)
{
if (dictionaryCheckBox.Any(f => f.Key == column) == false)
{
dictionaryCheckBox.Add(column, false);
this.InvalidateCell(column.HeaderCell);
}
}
else
{
dictionaryCheckBox.Remove(column);
this.InvalidateCell(column.HeaderCell);
}
}
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
base.OnCellPainting(e);
if (e.ColumnIndex >= 0 && e.RowIndex == -1 && dictionaryCheckBox.Any(f => f.Key == this.Columns[e.ColumnIndex]) == true)
{
Bitmap bmp = dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true ? bmCheckBox[1] : bmCheckBox[0];
Rectangle imageBounds = new Rectangle(new Point(e.CellBounds.Location.X + (e.CellBounds.Width / 2) - (bmp.Size.Width / 2), e.CellBounds.Location.Y + (e.CellBounds.Height / 2) - (bmp.Size.Height / 2)), bmp.Size);
e.PaintBackground(e.CellBounds, true);
e.PaintContent(e.CellBounds);
e.Graphics.DrawImage(bmp, imageBounds);
e.Handled = true;
}
}
protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
{
base.OnColumnHeaderMouseClick(e);
if (dictionaryCheckBox.ContainsKey(this.Columns[e.ColumnIndex]) == true)
{
var header = this.Columns[e.ColumnIndex].HeaderCell;
Bitmap img = dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true ? bmCheckBox[1] : bmCheckBox[0];
if (e.Button == System.Windows.Forms.MouseButtons.Left &&
e.Y >= header.ContentBounds.Y + (header.Size.Height / 2) - (img.Height / 2) &&
e.Y <= header.ContentBounds.Y + (header.Size.Height / 2) + (img.Height / 2) &&
e.X >= header.ContentBounds.X + (this.Columns[e.ColumnIndex].Width / 2) - (img.Width / 2) &&
e.X <= header.ContentBounds.X + (this.Columns[e.ColumnIndex].Width / 2) + (img.Width / 2))
{
dictionaryCheckBox[this.Columns[e.ColumnIndex]] = !dictionaryCheckBox[this.Columns[e.ColumnIndex]];
this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell);
executarValueChanged = false;
for (Int32 i = 0; i < this.Rows.Count; i++)
{
this.Rows[i].Cells[e.ColumnIndex].Value = dictionaryCheckBox[this.Columns[e.ColumnIndex]];
this.RefreshEdit();
}
executarValueChanged = true;
}
}
}
protected override void OnRowsAdded(DataGridViewRowsAddedEventArgs e)
{
base.OnRowsAdded(e);
List<DataGridViewColumn> listColunas = this.Columns.Cast<DataGridViewColumn>().Where(f => f.GetType() == typeof(DataGridViewCheckBoxColumn)).ToList();
foreach (DataGridViewColumn coluna in listColunas)
{
if (dictionaryCheckBox.ContainsKey(coluna) == true)
{
if (dictionaryCheckBox[coluna] == true)
{
executarValueChanged = false;
this.Rows[e.RowIndex].Cells[coluna.Index].Value = true;
this.RefreshEdit();
executarValueChanged = true;
}
}
}
}
protected override void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e)
{
base.OnRowsRemoved(e);
List<DataGridViewColumn> listColunas = this.Columns.Cast<DataGridViewColumn>().Where(f => f.GetType() == typeof(DataGridViewCheckBoxColumn)).ToList();
foreach (DataGridViewColumn coluna in listColunas)
{
if (dictionaryCheckBox.ContainsKey(coluna) == true)
{
if (this.Rows.Count == 0)
{
dictionaryCheckBox[coluna] = false;
this.InvalidateCell(coluna.HeaderCell);
}
else
{
Int32 numeroLinhas = this.Rows.Cast<DataGridViewRow>().Where(f => Convert.ToBoolean(f.Cells[coluna.Index].Value) == true).Count();
if (numeroLinhas == this.Rows.Count)
{
dictionaryCheckBox[coluna] = true;
this.InvalidateCell(coluna.HeaderCell);
}
}
}
}
}
protected override void OnCellValueChanged(DataGridViewCellEventArgs e)
{
base.OnCellValueChanged(e);
if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
{
if (dictionaryCheckBox.ContainsKey(this.Columns[e.ColumnIndex]) == true)
{
if (executarValueChanged == false)
{
return;
}
Boolean existeFalse = this.Rows.Cast<DataGridViewRow>().Any(f => Convert.ToBoolean(f.Cells[e.ColumnIndex].Value) == false);
if (existeFalse == true)
{
if (dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true)
{
dictionaryCheckBox[this.Columns[e.ColumnIndex]] = false;
this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell);
}
}
else
{
dictionaryCheckBox[this.Columns[e.ColumnIndex]] = true;
this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell);
}
}
}
}
protected override void OnCurrentCellDirtyStateChanged(EventArgs e)
{
base.OnCurrentCellDirtyStateChanged(e);
if (this.CurrentCell is DataGridViewCheckBoxCell)
{
this.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
}
use:
dataGridViewEx1.CheckBoxHeader(dataGridViewEx1.Columns[0] as DataGridViewCheckBoxColumn, true);
You must call the event click on the column
By identifying the column you clicked, you can access the desired row and change the value of the corresponding field
for example:
private void dataGridViewOrderState_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == dataGridViewOrderState.Columns["selectedDataGridViewCheckBoxColumn"].Index)
{
var bid = dataGridViewOrderState.Rows[e.RowIndex];
var selectedRow = (OrderStateLocal)bid.DataBoundItem;
if (selectedRow == null)
return;
selectedRow.Selected = !selectedRow.Selected;
}
}
private void AddHeaderCheckbox()
{
CheckBox cb = new CheckBox();
// your checkbox size
cb.Size = new Size(15, 15);
// datagridview checkbox header column cell size
var cell = dgv.Columns[0].HeaderCell.Size;
// calculate location
cb.Location = new Point((cell.Width - cb.Size.Width) / 2, (cell.Height - cb.Size.Height) / 2);
dgv.Controls.Add(cb);
}
I used the dataGridView_CellPainting event.
On that event I put in a conditional statement to set the location of my checkbox within the header cell - e.g. column 1 row 0.
CellBounds has a number of properties that can be used in setting the location. I took the right of the cell "e.CellBounds.Right" and then subtracted the width of the checkbox to put the checkbox in the right corner of the header cell.
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 1 && e.RowIndex == 0)
{
TopCheckBox.Left = e.CellBounds.Right - 15;
}
}
Hove missed something when you remove a column and add another at the same index
add this in the AddHeaderCheckBox function
Action onColRemoved = () =>
{
checkbox.Dispose();
};
dgv.ColumnRemoved += (s, e) => onColRemoved();
and modify this :
foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection) dgv.Rows : dgv.SelectedRows)
{
var val = row.Cells[column.Name].Value;
if (!(val is bool) || !(bool) val)
{
allAreTrue = false;
break;
}
}
into this
foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection) dgv.Rows : dgv.SelectedRows)
{
if (dgv.Columns.Contains(column.Name))
{
var val = row.Cells[column.Name].Value;
if (!(val is bool) || !(bool) val)
{
allAreTrue = false;
break;
}
}
}
this is another solution for the same problem. All you have to do is calling the constructor like showed following.
new ColocarHeaderCheckBox(dataGridView1, colActivo.Index);
Saludos.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Util
{
public class ColocarHeaderCheckBox
{
CheckBox headerCheckBox = new CheckBox();
int columnIndex = 0;
DataGridView dgv;
/// <summary>
/// Coloca un CheckBox en el Header del Datagriview para seleccionar o
/// deseleccionar todas las filas a la vez.
/// </summary>
/// <param name="dgv"></param>
/// <param name="columnIndex"></param>
/// (2022-08-29) Editado por Kong Fan
/// TODO
/// Falta hacer que el cuadro de checkbox pueda cambiar de tamano
public ColocarHeaderCheckBox(DataGridView dgv, int columnIndex)
{
// *** Asegurarse de que sea posible utilizar el HeaderCheckBox
if (!dgv.ColumnHeadersVisible) return;
if (!dgv.Columns[columnIndex].Visible) return;
if (dgv.Columns[columnIndex].CellType != typeof(DataGridViewCheckBoxCell)) return;
// *** Recibir parámetros
this.columnIndex = columnIndex;
this.dgv = dgv;
// *** Crear el HeaderCheckBox y enlazar eventos
CrearCheckBox();
// *** Muestra el estado inicial del HeaderCheckBox
CambiarEstadoHeaderCheckBox(this.dgv);
// *** Evento para controlar el scroll horizontal
dgv.Scroll += new ScrollEventHandler(Dgv_Scrolled);
}
private void Dgv_Scrolled(object sender, ScrollEventArgs e)
{
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
// *** Si se mueve el scroll vuelve a crear el control
dgv.Controls.Remove(headerCheckBox);
if (!CrearCheckBox()) dgv.Controls.Remove(headerCheckBox);
}
}
private bool CrearCheckBox()
{
int anchoCuadro = 14;
int altoCuadro = 14;
int anchoCelda = dgv.Columns[columnIndex].Width;
int altoCelda = dgv.ColumnHeadersHeight;
// *** Determinar la ubicación de la esquina superior izquierda de las columnas adyacentes
Point columnaUbicacion = dgv.GetColumnDisplayRectangle(columnIndex, true).Location;
Point columnaAntesUbicacion = new Point();
Point columnaDespuesUbicacion = new Point();
// *** Tomar ubicaciones de columnas antes y despues de la columna designada
bool tieneAntes = false;
bool tieneDespues = false;
for (int i = 0; i < dgv.Columns.Count; i++)
{
if (dgv.Columns[i].Visible && i < columnIndex && !tieneAntes)
{
columnaAntesUbicacion = dgv.GetColumnDisplayRectangle(i, true).Location;
tieneAntes = true;
}
if (dgv.Columns[i].Visible && i > columnIndex && !tieneDespues)
{
columnaDespuesUbicacion = dgv.GetColumnDisplayRectangle(i, true).Location;
tieneDespues = true;
}
}
// *** Comprobar si hay espacio para crear el control
if ((columnaDespuesUbicacion.X - columnaUbicacion.X) < (anchoCelda + anchoCuadro) / 2
&& dgv.FirstDisplayedScrollingColumnIndex != columnIndex)
return false;
if ((dgv.Width - columnaAntesUbicacion.X) < ((anchoCelda + anchoCuadro) / 2))
return false;
// *** Centrar la posición del headerCheckBox y el alto de la casilla
int posicionX = 0;
if (columnaDespuesUbicacion.X != 0)
posicionX = columnaDespuesUbicacion.X - (anchoCelda + anchoCuadro) / 2;
else
posicionX = columnaUbicacion.X + (anchoCelda - anchoCuadro) / 2;
if (altoCelda < (altoCuadro - 1)) altoCuadro = altoCelda - 2;
int posicionY = (altoCelda - altoCuadro) / 2 + 1;
// *** Agregar el control a la DataGridView
headerCheckBox.Location = new Point(posicionX, posicionY);
headerCheckBox.BackColor = Color.White;
headerCheckBox.Size = new Size(anchoCuadro, altoCuadro);
headerCheckBox.ThreeState = true;
dgv.Controls.Add(headerCheckBox);
// *** Asignar evento Click al headerCheckBox
headerCheckBox.Click += new EventHandler(HeaderCheckBox_Clicked);
// *** Asignar evento Click a las casillas de datos del DataGridView
dgv.CellContentClick += new DataGridViewCellEventHandler(DataGridView_CellClick);
return true;
}
private void HeaderCheckBox_Clicked(object sender, EventArgs e)
{
// *** Extraer del parámetro el sender.Parent la DataGriView
DataGridView dgv = (DataGridView)((CheckBox)sender).Parent;
// *** Necesario para finalizar cualquier edición
dgv.EndEdit();
// *** Recorrer todas las filas de la columna para checkar todos o ninguno
foreach (DataGridViewRow row in dgv.Rows)
{
if (headerCheckBox.CheckState == CheckState.Checked)
{
(row.Cells[columnIndex] as DataGridViewCheckBoxCell).Value = true;
headerCheckBox.Checked = true;
}
else
{
(row.Cells[columnIndex] as DataGridViewCheckBoxCell).Value = false;
headerCheckBox.Checked = false;
}
}
}
private void DataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = sender as DataGridView;
// *** Comprobar si está haciendo Click en la fila correcta
if (e.RowIndex >= 0 && e.ColumnIndex == columnIndex)
// *** Cambiar el estado del headerCheckBox
CambiarEstadoHeaderCheckBox(dgv);
}
private void CambiarEstadoHeaderCheckBox(DataGridView dgv)
{
int positivos = 0;
int negativos = 0;
int totalFilas = dgv.RowCount;
int contador = 0;
// *** Recorrer todas las filas y determinar uno de los 3 estados del headerCheckBox
foreach (DataGridViewRow fila in dgv.Rows)
{
contador++;
if ((bool)fila.Cells[columnIndex].EditedFormattedValue == true)
{
positivos++;
}
if ((bool)fila.Cells[columnIndex].EditedFormattedValue == false)
{
negativos++;
}
}
if (totalFilas == contador)
{
if (totalFilas == negativos)
{
headerCheckBox.CheckState = CheckState.Unchecked;
}
else if (totalFilas == positivos)
{
headerCheckBox.CheckState = CheckState.Checked;
}
else
{
headerCheckBox.CheckState = CheckState.Indeterminate;
}
}
}
}
}