Add image programmatically to nested ToolStripMenuItem via ImageIndex - c#

I have a menu structure as seen in picture below:
I want to add images to all submenu-items under the controllerToolStripMenuItem, ie openToolStripMenuItem, openInNewWindowToolStripMenuItem... ImageList contains my images to use and menuStrip1 gets a reference to the list of images :
menuStrip1.ImageList = ImageList;
Test code:
private void LoadSubMenuIcons()
{
menuStrip1.ImageList = ImageList;
//Just for test:
controllerToolStripMenuItem.ImageIndex = 2;
ToolStrip firstLevelParent = controllerToolStripMenuItem.GetCurrentParent();
//firstLevelParent.ImageList is of type MenuStrip
//firstLevelParent.ImageList equals ImageList set above
foreach (ToolStripItem subMenuItem in controllerToolStripMenuItem.DropDownItems)
{
if (subMenuItem is ToolStripMenuItem)
{
subMenuItem.ImageIndex = 2;
ToolStrip secondLevelParent = subMenuItem.GetCurrentParent();
//secondLevelParent is of type ToolStripDropDownMenu
//secondLevelParent.ImageList is null
}
}
}
In the example code above I try to add the image with index 2 to all submenu-items. This doesn't work! It might have to do with the fact that their parent is of type ToolStripDropDownMenu and its ImageList-property is null? The middle level item, controllerToolStripMenuItem, on the other hand shows the image correctly. Its parent is menuStrip1 which has a valid refrence to my imagelist. How do I solve the problem with the submenu-items?

Related

Images in the first column of a listview in C# WinForms

I'm with a little problem on a project.
As you can see in the image, I have a ListView with some data pulled from a List of objects from the class person. This class also has an attribute that keep the path of an image chosen by the user, which is supposed to show on the first column of the ListView, where it says teste.
I've tried the following code:
ImageList imgs = new ImageList();
imgs.ImageSize = new Size(40, 40);
foreach (user list in Global.userslist)
{
imgs.Images.Add(Image.FromFile(list.Photo));
}
listview1.SmallImageList = imgs;
foreach (user list in Global.userslist)
{
imageList1.Images.Add(Image.FromFile(list.Photo));
listview1.Items.Add(new ListViewItem(new string[] { "teste", Convert.ToString(list.Id), lista.Name, list.Birthday.ToString("dd/MM/yyyy") }));
}
You should set ImageIndex or ImageKey property for the item to show the image.
You can pass the index or key in constructor of ListViewItem. Also you can assign the value using the ImageIndex or ImageKey property.
Example
In your code, you can set the image key when adding them to ImageList:
imgs.Images.Add(list.Id.ToString(), Image.FromFile(list.Photo));
Then when creating items, use the ImageKey:
listview1.Items.Add(new ListViewItem(new string[] { ... ... }, list.Id.ToString()));

C# winform change selected tabcontrol image

I have a winform application written in C#. I had an imageList in my winform and I have a tabcontrol and each of the tab I assign a image as icon for the tab by changing ImageIndex.
However they have only 1 image for each tab and I want them to change to another image for the selected tab (like another highlighted image for active one). I have an idea to add all images to the imageList (both active and inactive images) and change the imageIndex of the selected tab. But I am not sure how to do it in practical.
Here are my current codes that I can come up with:
Inside SelectedIndexChange event, I have a function:
foreach (TabPage tab in tabControl1)
{
if (tab.index == tabControl1.SelectedIndex) { <---how to get the index?
tab.imageIndex = tab.index + tabControl1.TabCount;
} else {
tab.imageIndex = tab.index;
}
}
I came up with a solution
for (int i=0; i<tabControl1.TabPages.Count; i++)
{
if (tabControl1.TabPages[i] == tabControl1.SelectedTab)
{
tabControl1.TabPages[i].ImageIndex = i + tabControl1.TabPages.Count;
}
else
{
tabControl1.TabPages[i].ImageIndex = i;
}
}

How to add system icons in an imagelist in a listview

I have added icons in a imageList via using this code in the listview. Now I want them to be displayed whenever the list view of certain directory is shown.
My question is:
What changes would I need to make in imagelist1 control? And how to call imagelist1 in the code?
imageList1.Images.Add(
BlackFox.Win32.Icons.IconFromExtensionShell(
".*",
BlackFox.Win32.Icons.SystemIconSize.Small));
//lv.ImageIndex = 1;
If I understand you correctly you want to display the icons in the ImageList together with the corresponding files in the ListView. To do this you only need to point the SmallImageList or LargeImageList attribute of your ListView object to the ImageList (depending on the icon display mode your ListView uses).
private void UpdateListView() {
ImageList IconList = new ImageList();
IconList.Images.Add(
BlackFox.Win32.Icons.IconFromExtensionShell(".*",
BlackFox.Win32.Icons.SystemIconSize.Small));
YourListview.SmallImageList = IconList;
//Add the items to your Listview
}
Don't forget to assign the icons in the ImageList to the items in the ListView:
MyListItem.ImageIndex = 0;
or
MyListItem.ImageKey = "MyImageName";
or add them right away when you add your ListItems:
ListViewItem MyListItem= new ListViewItem("ItemName", "MyImageName");
ListViewItem MyListItem2= new ListViewItem("ItemName2", int ImageIndex);

Image not shown in tree view , C#

So in my project i would like have a nice treeview that has images.
but when i run the program the image was not shown. Any idea?
here is my code:
while (thisreader.Read()) // i read from the database.
{
TreeNode tn = new TreeNode();
tn.Text = thisreader["channel_name"].ToString();
tn.ImageIndex = 1;
tn.SelectedImageIndex = 1; // i have my imagelist1 in the corresponding winform
treeView1.Nodes.Add(tn);
}
The ImageList must be assigned to the ImageList property of the TreeView as well. Simply dropping it on the form is not enough.

Dynamic and Immutable UIElement Arrays

I have a WrapPanel that contains multiple Canvas of the same size. Each Canvas has some UIElements (i.e. TextBox, TextBlock, Buttons etc) as children. The creation of each Canvas (including its UIElement children) and the number of Canvas to be created are all done in run-time code behind (no XAML).
Initially I did the following, which works:
// declare as class properties, so all function can access them
WrapPanel wp = new WrapPanel();
Canvas[] cv = new Canvas[500];
TextBox[] tb = new TextBox[500];
// A function (e.g. a Button_Click event) that generates multiple Canvas in a WrapPanel
for (int i = 0; i<myInt; i++)
{
cv[i] = new Canvas();
tb[i] = new TextBox();
cv[i].Children.Add(tb[i]);
wp.Children.Add(cv[i]);
}
The above code is straight forwards works OK - Until I implement add, minus and destroy buttons where I could
1. Add an additional `Canvas` on a click event
2. Remove the last `Canvas` on a click event
3. Destroy a specific `Canvas` in the `WrapPanel` on a click event (may ba a little cross icon in each `Canvas`)
If I process some combination of the above 3 actions, I could easily create UIElements of the same index or create Canvas that goes out of the range of what it had been declared initially.
I looked into List however, each Canvas have different properties (each also has UIElement Children with different properties) and I can't figure out how List would solve it. A way for me to go around that is to declare a super large Array size for Canvas (e.g. Canvas[] cv = new Canvas[99999] but I though that's not very efficient.
Also, if I use List, how could I change properties of a specific UIElement after the they are generated? E.g. If i add 10 Canvas and add to List, and after they are all generated, I need to select the 5th Canvas and change a TextBox.Text, how do I access it like I did in an Array (i.e. tb[5].Text = "Hello")?
Can anyone show me some approaches to this problem?
Just a direct translation on how to do this with a list instead below. Given your code I don't know why you want to keep track of the canvas and textbox'es in a list - you can just access the children collection of the WrapPanel directly instead - let's assume you do need these separate collections for now.
WrapPanel wp = new WrapPanel();
List<Canvas> cvList = new List<Canvas>();
List<TextBox> tbList = new List<TextBox>();
public void Init()
{
int myInt = 500;
// in a function (e.g. a Button_Click event) to generate the multiple Canvas in a WrapPanel
for (int i = 0; i < myInt; i++)
{
Canvas cv = new Canvas();
TextBox tb = new TextBox();
cv.Children.Add(tb);
wp.Children.Add(cv);
cvList.Add(cv);
tbList.Add(tb);
}
}
public void AddCanvas()
{
Canvas cv = new Canvas();
TextBox tb = new TextBox();
cv.Children.Add(tb);
wp.Children.Add(cv);
cvList.Add(cv);
tbList.Add(tb);
}
public void RemoveCanvas()
{
wp.Children.RemoveAt(wp.Children.Count-1);
cvList.RemoveAt(cvList.Count - 1);
tbList.RemoveAt(cvList.Count - 1);
}
Edit for added comment:
E.g. If i add 10 Canvas, and after
they are all generated, I need to
select the 5th Canvas and change a
TextBox.Text, how do I access it like
I did in an Array (i.e. tb[5].Text =
"Hello")?
You can just access the children directly. You know you only added Canvas elements to your WrapPanel. So you could do (wp is the WrapPanel again):
TextBox textbox = (wp.Children[5] as Canvas).Children[0] as TextBox;
textbox.Text = "Hello";
Just operate directly on the WrapPanel's Children collection.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AddCanvasToWrapPanel(this.TestWrapPanel);
RemoveLastCanvasFromWrapPanel(this.TestWrapPanel);
AddCanvasToWrapPanel(this.TestWrapPanel);
DestroyCanvasAtWrapPanelIndex(this.TestWrapPanel, 0);
}
private void AddCanvasToWrapPanel(WrapPanel wp)
{
TextBox t = new TextBox();
Canvas c = new Canvas();
c.Children.Add(t);
wp.Children.Add(c);
}
private void RemoveLastCanvasFromWrapPanel(WrapPanel wp)
{
wp.Children.RemoveAt(wp.Children.Count - 1);
}
private void DestroyCanvasAtWrapPanelIndex(WrapPanel wp, int index)
{
wp.Children.RemoveAt(index);
}
}
}

Categories

Resources