ToolTip on ListView SubItem is not shown - c#

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.

Related

Can't raise click event of a UserControl in C#

I have a dynamically added UserControl:
var listItem = new ListItem(/* arguments */);
listItem.Click += SetListItemColor;
panel.Controls.Add(listItem); // "panel" is FlowLayoutPanel
SetListItemColor:
private void SetListItemColor(object sender, EventArgs e)
{
var listItem = (ListItem)sender;
if (listItem.BackColor == Color.LightGray)
{
listItem.BackColor = Color.White;
}
else
{
listItem.BackColor = Color.LightGray;
}
}
No change to the color happens when I click on the UserControl. However, for test purpose, I tried to change the event to EnabledChangedand change the Enabled property, the color does change:
var listItem = new ListItem(/* arguments */);
listItem.Enabled = false;
listItem.EnabledChanged += SetListItemColor;
listItem.Enabled = true;
panel.Controls.Add(listItem);
What's the problem?
EDIT:
Since docking doesn't work in a FlowLayoutPanel, suggest setting the size of your control to the size of the panel. Set the ListItem margins to empty as below to get maximum fill. For debugging set the backcolor different to make sure you can see it:
var listItem = new ListItem(/* arguments */);
listItem.BackColor = Color.Yellow; // Debugging only
listItem.Margin = Padding.Empty;
listItem.Size = panel.Size;
listItem.Click += SetListItemColor;
Note that if the control is resized you will need to resize your ListItem again.

How to select an item from a ListBox without using SelectionChange event

I am Silverlight developer and coding in C# to select an item from a list and display the selected item in the textBlock nearby.
My code to do so is:
ListBox lines = new ListBox();
TextBlock txtblkShowSelectedValue = new TextBlock();
ScrollViewer scrollViewer = new ScrollViewer();
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
lines.ItemsSource = param.Component.Attributes.Items;
Grid.SetColumn(lines, 1);
Grid.SetRow(lines, LoopCount);
childGrid.Children.Add(lines);
lines.SelectedIndex = 0;
lines.SelectedItem = param.Component.Attributes.Items;
The problem is how to select a value and how to display it in textblock "txtblkShowSelectedValue " ? because I cannot declare textblock and List variable globally because of current condition if I use selectionChange event
EDIT: The current scenario is :(lines (List) is in different function so it's not in scope of List_SelectionChanged() function)
private static Grid GenerateList(Parameter param, int LoopCount, Grid g)
{
Grid childGrid = new Grid();
ColumnDefinition colDef1 = new ColumnDefinition();
ColumnDefinition colDef2 = new ColumnDefinition();
ColumnDefinition colDef3 = new ColumnDefinition();
childGrid.ColumnDefinitions.Add(colDef1);
childGrid.ColumnDefinitions.Add(colDef2);
childGrid.ColumnDefinitions.Add(colDef3);
TextBlock txtblk1ShowStatus = new TextBlock();
TextBlock txtblkLabel = new TextBlock();
ListBox lines = new ListBox();
ScrollViewer scrollViewer = new ScrollViewer();
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
lines.ItemsSource = param.Component.Attributes.Items;
Grid.SetColumn(lines, 1);
Grid.SetRow(lines, LoopCount);
childGrid.Children.Add(lines);
lines.SelectedIndex = 0;
lines.SelectedItem = param.Component.Attributes.Items;
lines.SelectionChanged += new SelectionChangedEventHandler(List_SelectionChanged);
lines.SelectedIndex = lines.Items.Count - 1;
g.Children.Add(childGrid);
return (g);
}
static void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("clist _SelectionChanged1");
TextBlock txtblk1ShowStatus = new TextBlock();
txtblk1ShowStatus.Text = lines[(sender as ListBox).SelectedIndex];
}
This could be streamlined, but should work as a quick 'n dirty example of one way to solve the problem...
void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Grid g = null;
ListBox lb = sender as ListBox;
if (lb != null && lb.SelectedIndex >= 0)
{
// Find the top-level grid
var parent = VisualTreeHelper.GetParent(lb);
while (parent != null)
{
if (parent.GetType() == typeof(Grid))
{
if ((parent as Grid).Name.Equals("LayoutRoot"))
{
g = (Grid)parent;
break;
}
}
parent = VisualTreeHelper.GetParent(parent);
}
// Found the LayoutRoot, find the textblock
if (g != null)
{
for (int i = 0; i < g.Children.Count; i++)
{
var child = VisualTreeHelper.GetChild(g, i);
if (child is TextBlock)
{
(child as TextBlock).Text = (string)lb.SelectedItem;
break;
}
}
}
}
}
You could also name your textblock and search for that (as I did for "LayoutRoot").
Obviously, this code assumes the textblock is a child of the top-level Grid. Implementing a recursive search wouldn't be difficult.
lines.SelectionChanged+=new System.EventHandler(this.UpdateTextBlock); // add selectionchanged even for your listbox;
private void UpdateTextBlock(object sender, SelectionChangedEventArgs e)
{
txtblkShowSelectedValue.Text=this.lines[(sender as Listbox).SelectedIndex].ToString(); // just edit the content of your texblock
}
EDIT : thank you, and sorry to be late :-)
try this :
add parameter for the function, as this :
lines.SelectionChanged += new SelectionChangedEventHandler(List_SelectionChanged)
change parameter of this function and set your textblock as this :
static void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("clist _SelectionChanged1");
txtblkShowSelectedValue.Text=this.lines[(sender as Listbox).SelectedIndex].ToString()
}
Afteralli solved the problem like this:
lines.SelectionChanged += (o, e) =>
{
MessageBox.Show("clist _SelectionChanged1");
txtblk1ShowStatus.Text = lines.SelectedItem.ToString();
};
lines.SelectedIndex = lines.Items.Count - 1;
in my function GenerateList(..)

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;
}

c#: show tooltip on subitem

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, "");
}
}

How to change properties of a Control that is in List<UIControl> without using Loop?

I have the following code where a click event will dynamically create additional Canvas to the WrapPanel, and each Canvas contains a TextBox and a Button. Once the Button on one Canvas is click, TextBox.Text and Button.Content change from "Foo" to "Jesus".
The below code works, but it's not ideal. Because each property Change ("Foo" to "Jesus), I have to run a loop. I have to run two loops just to change the text on the TextBox and Button. Is there a direct way to change the Properties other then a Loop? My actually application contains 30+ controls in a Canvas, I don't want to run 30+ loops each time just to change some text.
List<Canvas> cvList = new List<Canvas>();
List<TextBox> tbList = new List<TextBox>();
List<Button> FooList = new List<Button>();
WrapPanel wp = new WrapPanel();
private void createbtn1_Click(object sender, RoutedEventArgs e)
{
Canvas cv = new Canvas();
StackPanel sp = new StackPanel();
TextBox tb = new TextBox();
Button Foo = new Button();
sp.Orientation = Orientation.Vertical;
sp.Children.Add(tb);
sp.Children.Add(Foo);
cv.Children.Add(sp);
wp.Children.Add(cv);
cvList.Add(cv);
tbList.Add(tb);
FooList.Add(Foo);
cv.Width = 100;
cv.Height = 100;
tb.Text = "#" + (cvList.IndexOf(cv)+1);
tb.Width = 50;
tb.Height = 30;
Foo.Content = "Foo";
Foo.Click += destroy_Click;
}
private void Foo_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
var bIndex = FooList.IndexOf(b);
foreach (TextBox t in tbList)
{
if (tbList.IndexOf(t) == bIndex)
{
t.Text = "Jesus";
}
}
foreach (Button f in FooList)
{
if (FooList.IndexOf(t) == bIndex)
{
t.Content = "Jesus";
}
}
}
Just access the text boxes by index and set the content of the button directly:
if(bIndex < tbList.Count && bIndex != -1)
tbList[bIndex].Text = "Jesus";
if(b != null && bIndex != -1)
b.Content = "Jesus";
why can't you just get the item at the index and set that items text:
tbList[bindex].Text="Jesus";
As for setting the buttons content, you already have the button from the click event, so just use that:
b.Content = "Jesus";
You current code just loops through each item in the list and gets the index of the item and sees if it is the index you want. Accessing by the indexer of the list directly will give you what you want.
You will probably want to do some error checking, but that is not currently done in your existing code either.
Some info on using indexers from MSDN

Categories