c#: show tooltip on subitem - c#

I have a listview, and in one of the columns (not the first) I want to display an error code.
What I haven't been able to do is get the ToolTip to display. I have
this.lstList.ShowItemToolTips = true;
...
ListViewItem value = lstList.Items.Add(name, name, 0);
...
if (lstList.Columns.Contains(lstColErrorCode))
{
value.SubItems.Add(new ListViewItem.ListViewSubItem(value, errorCode.ToString()));
value.ToolTipText = errorCode.ToString("X");
}
I would like to get the hex value of the code to be shown on the tooltip above the decimal value, but it shows above the name.
I haven't been able to get anything I tried to work (like trying to get the coordinates of the subitem). I would appreciate any suggestion.

this code works for me
ToolTip toolTip1 = new ToolTip();
void initMethod()
{
lstList.MouseMove += new MouseEventHandler(lstList_MouseMove);//mousemove handler
this.lstList.ShowItemToolTips = true;
toolTip1.SetToolTip(lstList,"");// init the tooltip
...
ListViewItem value = lstList.Items.Add(name, name, 0);
...
if (lstList.Columns.Contains(lstColErrorCode))
{
ListViewItem.ListViewSubItem lvs = value.SubItems.Add(new ListViewItem.ListViewSubItem(value, errorCode.ToString()));
lvs.Tag = "mydecimal"; // only the decimal subitem will be tooltiped
}
}
the mousemove event from the listview:
void lstList_MouseMove(object sender, MouseEventArgs e)
{
ListViewItem item = lstList.GetItemAt(e.X, e.Y);
ListViewHitTestInfo info = lstList.HitTest(e.X, e.Y);
if ((item != null) && (info.SubItem != null) && (info.SubItem.Tag!=null) && (info.SubItem.Tag.ToString() == "mydecimal"))
{
toolTip1.SetToolTip(lstList,((decimal)info.SubItem.Text).ToString("X"));
}
else
{
toolTip1.SetToolTip(lstList, "");
}
}

Related

Edit ListView Group Headers like we can edit ListViewItems

In a WinForms app, we can re-name ListView Items by clicking them twice. Can we somehow rename Group Headers the same way? Is there a way to enable this?
I guess it is doable after all, albeit not by simply enabling a property..
Note: The code below assumes that the ListView is in Details mode!
The trick to tell a Group from emtpy space is to test the right side of the ListView. Another trick is to wait a little: The click will select the Group Items. Only after that can we proceed..
Here is an example that overlays the Group with a TextBox:
// class variable to test if have been hit twice in a row
ListViewGroup lastHitGroup = null;
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
// check left side to see if we are at the empty space
ListViewItem lvi = listView1.GetItemAt(4, e.Y);
// yes, no action! reset group
if (lvi != null) { lastHitGroup = null; return; }
// get the height of an Item
int ih = listView1.GetItemRect(0).Height;
// to get the group we need to check the next item:
ListViewItem lviNext = listView1.GetItemAt(4, e.Y + ih);
// no next item, maybe the group is emtpy, no action
if (lviNext == null) return;
// this is our group
ListViewGroup editedGroup = lviNext.Group;
// is this the 2nd time?
if (lastHitGroup != editedGroup) {lastHitGroup = editedGroup; return;}
// we overlay a TextBox
TextBox tb = new TextBox();
tb.Parent = listView1;
// set width as you like!
tb.Height = ih;
// we position it over the group header and show it
tb.Location = new Point(0, lviNext.Position.Y - ih - 4);
tb.Show();
// we need two events to quit editing
tb.KeyPress += (ss, ee) =>
{
if (ee.KeyChar == (char)13) // success
{
if (editedGroup != null && tb.Text.Length > 0)
editedGroup.Header = tb.Text;
tb.Hide();
ee.Handled = true;
}
else if (ee.KeyChar == (char)27) // abort
{
tb.Text = ""; tb.Hide(); ee.Handled = true;
}
};
tb.LostFocus += (ss, ee) => // more success
{
if (editedGroup != null && tb.Text.Length > 0)
editedGroup.Header = tb.Text;
tb.Hide();
};
// we need to wait a little until the group items have been selected
Timer lvTimer = new Timer();
lvTimer.Interval = 333; // could take longer for a huge number of items!
lvTimer.Tick += (ss,ee) => { tb.Focus(); lvTimer.Stop();};
lvTimer.Start();
}

ToolTip on ListView SubItem is not shown

I am unable to show tooltips on ListView subitems. Involved implementation is:
ListView sqlView = new ListView() { Dock = DockStyle.Fill, View = View.Details, MultiSelect = true, FullRowSelect = true, HeaderStyle = ColumnHeaderStyle.Nonclickable, GridLines = true };
...
sqlView.ShowItemToolTips = true;
sqlView.MouseMove += sqlView_MouseMove;
...
// filled in foreach, don't worry it's correct here ;)
item.SubItems[columnIndex].Text = "✔";
item.SubItems[columnIndex].Tag = ("via: '" + sqlEntry.Login + "'");
Mouse event handler method:
void sqlView_MouseMove(object sender, MouseEventArgs e)
{
ListView sqlView = ((ListView)sender);
ListViewItem item = sqlView.GetItemAt(e.X, e.Y);
ListViewHitTestInfo info = sqlView.HitTest(e.X, e.Y);
if (item != null && info.SubItem != null && info.SubItem.Tag != null)
{
ToolTip tt = new ToolTip();
//tt.ShowAlways = true; - no effect
//tt.Active = true; - no effect
tt.SetToolTip(sqlView, (String)info.SubItem.Tag);
}
}
Events are firing. Subitems Tags are filled properly. No Tooltip shown. Why?
Thx for help.
Don't create a new ToolTip() each time through. Just create one and reuse it.

Find Label by Name in a UserControl when the label's Parent is a PictureBox

I have a user control with multiple pictureboxes and labels on them.
I need to put each Label (lb) on his own Picturebox (pbParent), and the label Backcolor must be transparent to improve PictureBox Image visibility under this picture box.
Picture boxes are named TabFrame0 to TabFrameN, and the Labels are named Label0 to LabelN.
I have a function GetLabelByTag that must return the label searched by its name. It works fine until I make the Label's parent the PictureBox (see row 8). So, my questions is: how do I find the label if it's parent become a pictureBox, not my UserControl, which collection do contain it?
void CreateControls()
{
...
newLabel.Name = TAB_PIC_BOX_LABEL_NAME + _id.ToString(); //1
newLabel.Text = _text;//2
newLabel.Tag = _id;//3
newLabel.AutoSize = true;//4
Controls.Add(newLabel);//5
Label lb = GetLabelByTag(_id, TAB_PIC_BOX_LABEL_NAME);//6
PictureBox pbParent = GetPicBoxByTag(_id, TAB_PIC_BOX_CONTROL_NAME);//7
lb.Parent=pbParent;//8
lb.BringToFront();//9
...
}
...
Label GetLabelByTag(int _tag, string _family)
{
Label rez = new Label();
foreach (Control lb in Controls)
{
if (lb.Tag != null)
{
if (((int)lb.Tag == _tag) && (lb.Name == _family + _tag.ToString()))
{
rez = (Label)lb;
}
}
}
return rez;
}
You need to recursively iterate the children's children if there are any. E.g. like this:
Label GetLabelByTag(int _tag, string _family)
{
return FindLabelByTag(_tag, _family, this);
}
Label FindLabelByTag(int _tag, string _family, Control _control)
{
Label rez = null;
foreach (Control lb in _control.Controls)
{
if (lb.Tag != null)
{
if (((int)lb.Tag == _tag) && (lb.Name == _family + _tag.ToString()))
{
return (Label)lb;
}
}
var inControl = FindLabelByTag(_tag, _family, lb);
if (inControl != null)
return inControl;
}
return null;
}

How to set tooltip for a ListviewSubItem

I have a ListView control in Details view as that (the view that shows the list as a grid)
mListView.View = View.Details;
mListView.mLVSelectedObject.ShowItemToolTips = true;
ListViewItem listViewItem = mListView.Items.Add(lValue.Name);
listViewItem.ToolTipText = "AAAAAAAAAAAAAAAAA";
The issue is that the tooltip only shows up when the cursors is over the first listview's column but not for the rest o them. I want to know if there's anyway to make it appear "easly" ?
After some research. I've solved the issue this way, but I'm still wondering if there is another way to do that avoiding EventHandlers;
ToolTip mTooltip;
Point mLastPos = new Point(-1, -1);
private void listview_MouseMove(object sender, MouseEventArgs e)
{
ListViewHitTestInfo info = mLV.HitTest(e.X, e.Y);
if (mTooltip == null)
mTooltip = new ToolTip();
if (mLastPos != e.Location)
{
if (info.Item != null && info.SubItem != null)
{
mTooltip.ToolTipTitle = info.Item.Text;
mTooltip.Show(info.SubItem.Text, info.Item.ListView, e.X, e.Y, 20000);
}
else
{
mTooltip.SetToolTip(mLV, string.Empty);
}
}
mLastPos = e.Location;
}

How can I change the ForeColor of a single sub item in a ListView control?

I have a Windows Form application in which I have a ListView control. I want to change the forecolor of a single subitem. Although I have managed to change the color of a entire row or column, I haven't figured out a way to do this for a single subitem. Does anyone know of a way to do this?
The solution is fairly simple, and is indicated in the Remarks section of the documentation for the ListViewSubItem.ForeColor property:
If the UseItemStyleForSubItems property of the ListViewItem that owns the subitem is set to true, setting this property has no effect.
The default setting is intended to maintain a consistent appearance for all subitems owned by a single item in a ListView control so that you only have to change the properties in one place. To change the default behavior, you need to set the UseItemStyleForSubItems property of a particular ListViewItem to "False".
Once you've done that, you can adjust the ForeColor (or any other) property of an individual subitem. For example:
myListView.Items[0].UseItemStyleForSubItems = false;
myListView.Items[0].SubItems[1].ForeColor = Color.Red;
A way would be to set the color for all the subitems and change for the one you want.
Example code:
private void btn_Add_Click(object sender, EventArgs e)
{
ListViewItem lvi = new ListViewItem();
ListViewItem.ListViewSubItem lvsi1 = new ListViewItem.ListViewSubItem();
ListViewItem.ListViewSubItem lvsi2 = new ListViewItem.ListViewSubItem();
lvi.Text = tb_Main.Text;
lvsi1.Text = tb_Sub1.Text;
lvsi2.Text = tb_Sub2.Text;
lvi.UseItemStyleForSubItems = false;
lv_List.ForeColor = Color.Black;
if (lvsi1.Text == tb_Different.Text)
{
lvsi1.ForeColor = Color.Red;
}
if (lvsi2.Text == tb_Different.Text)
{
lvsi2[2].ForeColor = Color.Red;
}
lv_List.Items.Add(lvi);
lvi.SubItems.Add(lvsi1);
lvi.SubItems.Add(lvsi2);
}
This example will color every sub Item that has the value "Monday"
public static void colorList(ListView lsvMain)
{
foreach (ListViewItem lvw in lsvMain.Items)
{
lvw.UseItemStyleForSubItems = false;
for (int i = 0; i < lsvMain.Columns.Count; i++)
{
if (lvw.SubItems[i].Text.ToString() == "Monday")
{
lvw.SubItems[i].BackColor = Color.Red;
lvw.SubItems[i].ForeColor = Color.White;
}
else {
lvw.SubItems[i].BackColor = Color.White;
lvw.SubItems[i].ForeColor = Color.Black;
}
}
}
}
Here's how I did it to show results of a multi-client SCCM push/remove. The CSV passed was (string ClientName,string PackageName,string EventType,bool Result), but I wanted to display the longest field, Package Name last, and have the Results where it'd be easier to see the color for success/fail.
private void MultiClientResultForm_Load(object sender, EventArgs e)
{
foreach (string token in Main.ClientListResults)
{
string[] ResultRecord = token.Split(new string[] { "," }, StringSplitOptions.None);
if (ResultRecord[0] != "")
{
ListViewItem row = new ListViewItem(ResultRecord[0]);
row.SubItems.Add(new ListViewItem.ListViewSubItem(row, ResultRecord[2]));
if (ResultRecord[3] == "true")
{
row.SubItems.Add(new ListViewItem.ListViewSubItem(row, "Success"));
row.SubItems[2].ForeColor = Color.ForestGreen;
}
else
{
row.SubItems.Add(new ListViewItem.ListViewSubItem(row, "Fail"));
row.SubItems[2].ForeColor = Color.DarkRed;
}
row.SubItems.Add(new ListViewItem.ListViewSubItem(row, ResultRecord[3]));
row.SubItems.Add(new ListViewItem.ListViewSubItem(row, ResultRecord[1]));
listViewResults.Items.Add(row);
}
}
}

Categories