I need to show a tooltip while the mouse hovers on WinForms RadGridView header cells. The tooltip's text is different based on the current cell the mouse is hovering on. I don't want the tooltip to be disappeared until the mouse leaves the cell.
Maximum time is about 24 days... I suppose it's enough :)
Best way is to use ToolTipTextNeeded event:
private void radGridView1_ToolTipTextNeeded(object sender, ToolTipTextNeededEventArgs e)
{
// if cursor hover GridHeaderCellElement
var header = radGridView1.ElementTree.GetElementAtPoint(PointToClient(MousePosition)) as GridHeaderCellElement;
if (header != null)
{
e.ToolTip.AutoPopDelay = int.MaxValue; // 24.86 days
e.ToolTipText = "123";
}
}
or ( tnx to #checho )
private void radGridView1_ToolTipTextNeeded(object sender, ToolTipTextNeededEventArgs e)
{
// if cursor hover GridHeaderCellElement
if (sender is GridHeaderCellElement)
{
e.ToolTip.AutoPopDelay = int.MaxValue; // 24.86 days
e.ToolTipText = "123";
}
}
Related
In my Winform 4.5 app, I have a DataGridView with first column as a link column. I would like to have the link color of the selected link cell to be white. Since by default the background color of a selected row (or a cell) is blue and the ForeColor of all the links are also blue, when user selects a row (or a link cell) the text of the link is not readable. I tried writing the following code but it does not change the link color of selected link cell at all.
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
foreach (DataGridViewLinkCell cell in ((DataGridView)sender).SelectedCells)
{
if (cell.ColumnIndex == 0)
{
if (cell.Selected)
{
cell.Style = new DataGridViewCellStyle()
{
SelectionForeColor = SystemColors.HighlightText
};
}
}
}
}
I then modified the above code as follows. But it changes the link color of all the links to white - that makes non-selected link cells to be not readable since the backcolor of those links is also white:
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
foreach (DataGridViewLinkCell cell in ((DataGridView)sender).SelectedCells)
{
if (cell.ColumnIndex == 0)
{
if (cell.Selected)
{
cell.LinkColor = SystemColors.HighlightText;
}
}
}
}
I tested both the codes by setting a breakpoint inside the foreach loop and selecting a link cell. I noticed that the code does go through exactly one iteration of the foreach loop correctly. Moreover, I have made no change to the default settings of the DataGridViewLinkColumn
Edit
By default the DataGridView looks like this on a row selection. Notice that the cell in the second column changes its ForeColor to white but not the cell in the first column:
I want it to looks like this on a row selection:
Edit The CellLeave event will always occur when an attempt is made to navigate away from a cell.
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
foreach (DataGridViewLinkCell cell in
((DataGridView) sender).SelectedCells.OfType<DataGridViewLinkCell>())
{
if (cell.Selected)
{
cell.LinkColor = SystemColors.HighlightText;
}
}
}
private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
foreach (DataGridViewLinkCell cell in
((DataGridView) sender).Rows[e.RowIndex].Cells.OfType<DataGridViewLinkCell>())
{
cell.LinkColor = cell.LinkVisited ? Color.Purple : Color.Blue;
}
}
I've experienced the same issue and I got it working using the CellFormatting event. Below you'll find a generic solution for this:
void grd_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
SetGridLinkColor(sender as DataGridView, e.RowIndex, e.ColumnIndex, Color.White);
}
public static void SetGridLinkColor(DataGridView grd, int rowIndex, int columnIndex, Color selectedColor)
{
if (grd == null || !(grd.Columns[columnIndex] is DataGridViewLinkColumn))
return;
if (grd.Rows[rowIndex].Selected)
{
((DataGridViewLinkCell)grd.Rows[rowIndex].Cells[columnIndex]).LinkColor = selectedColor;
((DataGridViewLinkColumn)grd.Columns[columnIndex]).VisitedLinkColor = selectedColor;
}
else
{
Color color = ((DataGridViewLinkColumn)grd.Columns[columnIndex]).LinkColor;
((DataGridViewLinkCell)grd.Rows[rowIndex].Cells[columnIndex]).LinkColor = color;
((DataGridViewLinkColumn)grd.Columns[columnIndex]).VisitedLinkColor = color;
}
}
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.
I'd like to know is it possible to:
While f1 key is pressed show tooltips of all buttons in wrappanel.
Code:
myButton.ToolTip = new ToolTip() { Content = "[CTRL + 1]" };
And I think I can handle 'while f1 is pressed', but have no idea how to show tooltip right under button (right now, when f1 is pressed, tooltip appears near cursor position).
Thanks in advance!
You can set ToolTipService.Placement="Bottom" on your Button to show tooltip at bottom.
ToolTipService.SetPlacement(myButton, System.Windows.Controls.Primitives.PlacementMode.Bottom);
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F1)
{
((ToolTip)button1.ToolTip).PlacementTarget = button1;
((ToolTip)button1.ToolTip).Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
((ToolTip)button1.ToolTip).IsOpen = true;
}
}
I have a WPF ListBox operating in single selection mode. I am adding drag and drop to move items around. Currently the ListBox selection responds to both left button pressed and then with mouse moves with left button down. So after I wait for the MinimumVerticalDragDistance to start a drag operation, a different item could be selected. Dragging either the unselected orginal item or dragging the new selected item is confusing. Adding 'e.Handled=true' in xxx_MouseMove or xxx_PreviewMouseMove does not do anything. Any ideas on suppressing this selection due to mouse moves with left button down?
The best kludge I came up with is to cancel the ListBox's "Selection by dragging" in the IsMouseCapturedChanged event.
public partial class MainWindow : Window
{
Rect? dragSourceGestureRect;
bool busy;
public MainWindow()
{
InitializeComponent();
listBox.ItemsSource = Enumerable.Range(1, 9);
listBox.PreviewMouseLeftButtonDown += listBox_PreviewMouseLeftButtonDown;
listBox.IsMouseCapturedChanged += listBox_IsMouseCapturedChanged;
listBox.MouseMove += listBox_MouseMove;
}
void listBox_IsMouseCapturedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (busy)
return;
if (!listBox.IsMouseCaptured)
dragSourceGestureRect = null;
else if (dragSourceGestureRect.HasValue)
{
busy = true;
{
//tell the ListBox to cancel it's "Selection by dragging"
listBox.ReleaseMouseCapture();
//Now recapture the mouse for canceling my dragging
listBox.CaptureMouse();
}
busy = false;
}
}
void listBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var center = e.GetPosition(listBox);
dragSourceGestureRect = new Rect(
center.X - SystemParameters.MinimumHorizontalDragDistance / 2,
center.Y - SystemParameters.MinimumVerticalDragDistance / 2,
SystemParameters.MinimumHorizontalDragDistance,
SystemParameters.MinimumVerticalDragDistance);
}
void listBox_MouseMove(object sender, MouseEventArgs e)
{
if (!dragSourceGestureRect.HasValue || dragSourceGestureRect.Value.Contains(e.GetPosition(listBox)))
return;
dragSourceGestureRect = null;
var data = new DataObject(DataFormats.UnicodeText, "The Data");
DragDrop.DoDragDrop(listBox, data, DragDropEffects.Copy);
e.Handled = true;
}
}
i want to have a tooltip for each item in a treeview, and each item in a listview, and different for each subitem (i.e. column) in the listview.
i can determine the text i want to show (using hit testing with the current mouse position, etc):
private void toolTip1_Popup(object sender, PopupEventArgs e)
{
if (e.AssociatedControl == listView1)
{
toolTip1.SetToolTip(listView1, "foo");
}
}
but any attempt to set the tooltip text causes a stackoverflow.
How can i customize the tooltip (icon, title, text) just before it appears?
You need to guard your code in the Popup event handler so that if you are calling SetToolTip from within it, you don't call SetToolTip again.
Something like:
private bool updatingTooltip;
private void toolTip1_Popup(object sender, PopupEventArgs e)
{
if (!this.updatingTooltip && (e.AssociatedControl == listView1))
{
this.updatingTooltip = true;
toolTip1.SetToolTip(listView1, "foo");
this.updatingTooltip = false;
}
}