I'm not very experienced on c#. I'm working with winforms and I'm looking for a way to create something like a list of elements with this template , something like the autocompletion list of visual studio.
Is it possible to do? Shall I use listbox or listview?
EDIT
Sorry my question wasn't clear I don't want to create an autocomplete but what i want to create is something like this a list of things with an icon next to the text of that thing.
As I understand from your question, you can create custom UserControl or create a Form and put ListBox in it. If you use From be sure that you change border style layout, just set it to none. After creation for use it you should create form and show it where you want like this:
FrmAutoComplete x = new FrmAutoComplete();
x.Show();
you can put this form in ToolTipItem and show it.
Good luck.
THis is a quick and dirty example of using images in your Listview control. Since I don;t have a lot of information about what you plan to do, I tried to keep is simple.
In short, you need to load some images into one of the ImageLists (Large or Small) built into the Listview control and assign them keys so that you can assign them to specific list items as you add them.
The trick to this is determining which image to use for a specific list item (assuming there are different images assigned to different list items depending on some differentiating factor. For this example, I used an arbitrary assignment of "cars" or "trucks," and simply decided that the first five items in the list would be cars, and the last five would be trucks. I then assigned each image appropriately, using the image key as I added each listview item. You can do this for more complex scenarios, and when using the image key, it does not matter what order the items are added.
For this use case, you will want to create or use images with dimensions of 16 x 16 pixels. I went ahead and added two images to my project resource file, then simply accessed them using the project Properties.Resources name space. There are other ways to do this as well, but this is the most convenient for me.
Hope that helps.
public partial class Form1 : Form
{
static string CAR_IMAGE_KEY = "Car";
static string TRUCK_IMAGE_KEY = "Truck";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.SetupListview();
this.LoadListView();
}
private void SetupListview()
{
var imgList = new ImageList();
imgList.Images.Add("Car", Properties.Resources.jpgCarImage);
imgList.Images.Add("Truck", Properties.Resources.jpgTruckImage);
var lv = this.listView1;
lv.View = View.List;
lv.SmallImageList = imgList;
}
private void LoadListView()
{
for(int i = 1; i <= 10; i++)
{
string currentImageKey = CAR_IMAGE_KEY;
if(i > 5) currentImageKey = TRUCK_IMAGE_KEY;
var item = this.listView1.Items.Add("Item" + i.ToString(), currentImageKey);
}
}
Related
First of all I am from Iran and I can't speak English very well, sorry for this.
I made something like OpenFileDialog in WinForms and it works correctly.
After that for better User Interface I'm try to make it in WPF.
I use TreeView and other controls to make it work in both platforms (Winforms and WPF).
In WPF I want to get the text of Treeview item for comparison, in Winform I could do this with below code:
private void Folder_FileTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
{
if(e.Node.Text=="Desktop")
{
//Do something
}
}
in WPF I added text with and image next to each other using this method:
public object Node(string NodeIMGUri, string NodeText)
{
Image IMG = new Image() { Source = new System.Windows.Media.Imaging.BitmapImage(new Uri(NodeIMGUri, UriKind.RelativeOrAbsolute)) };
TextBlock Text = new TextBlock() { Text = NodeText };
StackPanel CustomStackPanel = new StackPanel();
TreeViewItem TVItem = new TreeViewItem();
IMG.Height = 50;
IMG.Width = 50;
CustomStackPanel.Orientation = Orientation.Horizontal;
CustomStackPanel.Children.Add(IMG);
CustomStackPanel.Children.Add(Text);
TVItem.Header = CustomStackPanel;
return TVItem;
}
But when in SelectedItemChanged (or ItemChanged) event of TreeView how can I get the text of the item clicked?
If anyone can help me to complete this dll, I can send it free to all programmers.
This dll supports most languages like german, france, china, hindi, bengali, indonesian, persian, japanese, korean, arabic, portuguese, latin, swede, english
The way you are currently doing things, you would need to go through the children of your item to find the TextBlock and get the Text property from that. But this isn't the proper or recommended way of doing things in WPF.
Instead of manually creating TreeViewItems, you shoudl be using TreeView.ItemsSource and TreeView.ItemTemplate. If you're not familiar with how to use DataTemplates in WPF, you should really read up on it. Here is a good place to start.
Basically you would define a class, let's say Folder, then you would have a collection of Folder objects (e.g. List<Folder>), and you would bind that to TreeView.ItemsSource. You would then use a DataTempalte to declare the visual representation of how a Folder object should look in the TreeView. Then, when the selected item is changed, you can use TreeViewItem.DataContext to get the Folder object that is being selected, which would probably have a property such as Path.
So what I can see there you put into your TreeViewItem's header a panel with two items - Image and TextBlock with Text you want to get. The TextBlock is stored as the second item in the panel's collection (Children). All you have to do is this:
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
CustomStackPanel panel = (CustomStackPanel)((TreeViewItem) e.NewValue).Header;
TextBlock textBlock = (TextBlock)panel.Children[1];
string text = textBlock.Text; //Your text
}
Hope it helps.
I'm working on a small program as part of my A Level Computing course that is designed to track orders. It is written in C# using the Windows Forms.
I am having an issue where I enter all the information for a new order and then press OK and it should update the ListView with the information. I have my ListView in Detail view with 4 columns but nothing ever gets added to the ListView. The section of code that should add the items to the ListView is being executed and is not throwing any errors or causing the program to crash but nothing is being added. Its weird because I am using the exact same method that I used in my little prototype mock up but for some reason now it is not working.
All the things I've found on here or on the internet seem to suggest its an issue with the View mode of the ListView and I've tried modifying this property to no avail.
Any ideas why this section of code is refusing to add anything to the ListView?
//Create an array to store the data to be added to the listbox
string[] orderDetails = { Convert.ToString(id + 1), rNameBox.Text, dateBox.Value.ToString(), orderBox.Text };
//DEBUGGING
Console.WriteLine(orderDetails[0]);
Console.WriteLine(orderDetails[1]);
Console.WriteLine(orderDetails[2]);
Console.WriteLine(orderDetails[3]);
//END DEBUGGING
//Add the order info to the ListView item on the main form
var listViewItem = new ListViewItem(orderDetails);
ths.listView1.Items.Add(listViewItem);
If you need any more information just say. Apologies if this is in the wrong format or something this is my first time here.
Your problem is that your ListViewItem contains a string array and it has no useful way of displaying it.
What you should be doing (there are a number of ways of doing this, but here's one) is creating a class, OrderDetail, with an Id, a Name, a Date, and so on. Give it a ToString() method (public override string ToString()) which returns what you want to display, e.g.:
public override string ToString()
{
return this.Name;
}
Create an instance of OrderDetail and set its properties. Create ListViewItem giving it the OrderDetail instance and add to the ListView. Repeat for as many OrderDetail instances you want.
Cheers -
Added: code which works:
int id = 12;
string rNameBoxText = "rName";
DateTime dateBoxValue = DateTime.Now;
string orderBoxText = "order";
string[] orderDetails = { Convert.ToString(id + 1), rNameBoxText, dateBoxValue.ToString(), orderBoxText };
//DEBUGGING
Console.WriteLine(orderDetails[0]);
Console.WriteLine(orderDetails[1]);
Console.WriteLine(orderDetails[2]);
Console.WriteLine(orderDetails[3]);
//END DEBUGGING
this.listView1.Columns.Clear();
this.listView1.Columns.Add("Id");
this.listView1.Columns.Add("rName");
this.listView1.Columns.Add("Date");
this.listView1.Columns.Add("Order");
this.listView1.View = View.Details;
//Add the order info to the ListView item on the main form
var listViewItem = new ListViewItem(orderDetails);
this.listView1.Items.Add(listViewItem);
I've found similar answers to my question before, but not quite to what I'm trying to do...
In Visual Basic (last I used it, in 06/07) there was an "Index" property you could assign to multiple controls with the same name. I used this primarily to loop through controls, i.e.:
For i = 1 to 500
picSeat(i).Print "Hello"
Next i
Is there a way to do this in C#? I know there is a .IndexOf(), but would that really help for what I'm doing? I want to have multiple controls with the same name, just different index.
This is a Windows Form Application, and I'm using Visual Studio 2012. I am talking about controls, not arrays/lists; this was possible in VB and I was wondering if it was possible at all in C#. So I want to have, say, 30 seats in a theatre. I want to have each seat represented by a picturebox named "picSeat". VB would let me name several objects the exact same, and would assign a value to a control property "Index". That way, I could use the above loop to print "Hello" in every picture box with only 3 lines of code.
No, this feature does not exist in C#, and was never implemented in the transition from classic VB to VB.Net.
What I normally do instead is put each of the controls in question in a common parent container. The Form itself can work, but if you need to distinguish these from others of the same type a GroupBox or Panel control will work, too. Then, you access the controls like this:
foreach (var picBox in parentControl.Controls.OfType<PictureBox>())
{
// do something with each picturebox
}
If you want to use a specific control, just write by name:
pictureBox6.SomeProperty = someValue;
If you need to change a specific control determined at run-time, normally this is in response to a user event:
void PictureBox_Click(object sender, EventArgs e)
{
var picBox = sender As PictureBox;
if (picBox == null) return;
//picBox is now whichever box was clicked
// (assuming you set all your pictureboxes to use this handler)
}
If you really really want the Control Arrays feature, you can do it by adding code to create the array to your form's Load event:
PictureBox[] pictureBoxes = Me.Controls.OfType<PictureBox>().ToArray();
Are we talking WinForms here? I'm not sure, but I don't think you can have multiple controls in winforms with same name. But I vaguely recall doing something similar and the solution was to name them Button_1, Button_2 etc. Then you can iterate through all controls and get your own index.
Beware though that if you want to instanciate a separate control for each seat in a theatre, you might run into some serious performance issues :) I've done something similar to that as well and ended up drawing the whole thing on a canvas and using mouse coordinates to handle the events correctly.
You may want to check out the Uid property of controls.
(http://msdn.microsoft.com/en-us/library/system.windows.uielement.uid(v=vs.110).aspx)
You can access Control through Uid property with the following
private static UIElement FindUid(this DependencyObject parent, string uid)
{
var count = VisualTreeHelper.GetChildrenCount(parent);
if (count == 0) return null;
for (int i = 0; i < count; i++)
{
var el = VisualTreeHelper.GetChild(parent, i) as UIElement;
if (el == null) continue;
if (el.Uid == uid) return el;
el = el.FindUid(uid);
if (el != null) return el;
}
return null;
}
And simply use
var control = FindUid("someUid");
I copied code from this post
If you create an indexed dictionary of your user control, it will behave pretty much the same as in VB6, though you'll not see it on the VS C# GUI. You'll have to get around the placement issues manually. Still - and most importantly -, you'll be able to refer to any instance by the index.
The following example is for 3 pieces for clarity, but of course you could automate every step of the process with appropriate loops.
public partial class Form1 : Form
{
...
Dictionary<int, UserControl1> NameOfUserControlInstance = new Dictionary<int, UserControl1>()
{
{ 1, new UserControl1 {}},
{ 2, new UserControl1 {}},
{ 3, new UserControl1 {}}
};
private void Form1_Load(object sender, EventArgs e)
{
NameOfUserControlInstance[1].Location = new System.Drawing.Point(0, 0);
NameOfUserControlInstance[2].Location = new System.Drawing.Point(200, 0);
NameOfUserControlInstance[3].Location = new System.Drawing.Point(400, 0);
Controls.Add(NameOfUserControlInstance[1]);
Controls.Add(NameOfUserControlInstance[2]);
Controls.Add(NameOfUserControlInstance[3]);
}
...
}
I like using Tags to apply any type of meta data about the controls
for (int i = 0; i< 10; ++i)
{
Button button = new Button();
button.Tag = i;
}
in my Win Forms app I create an array of dynamic custom controls inside a loop. These, lets call them 'boxes', are like my basic pieces of information. I also create string arrays in other parts of the code that contain the information of this 'boxes', so that for example string[3] is a variable of box[3] and so does stringa[3], stringb[3], stringc[3]... all the arrays with the same index are related to the box with that index. Hope I make myself clear.
Only 2 of this strings are shown in 2 labels inside each custom control 'box' in the array, but the others are there because I want to make something so that when the user clicks one of these controls the other strings can be shown in another control. Sort of something like "More Information...". All the 'boxes' in the array need to have the same event handler because I create +100.
To put it more into context, each custom control 'box' in the array shows the Symbol and the Price of a stock and I want that when the user clicks on each stock more quote information is shown on another special control which is like a placeholder for "More info".
I am thinking of 2 ways to do it:
If I could "detect" the index of the clicked control (which is the same in the strings related to it), I could just set this to an int j and all I have to do is show all the strings a,b,c... with index j. Unfortunately I cannot find a way to do this, maybe it is not even possible.
The other way I have thought is to create some properties for my custom control which "store" this variables, and in my app instead of assigning strings I would set properties for each control, which I could later retrieve when the control is clicked. I haven't tryed this because I don't know exactly how to do it.
What do you think? Do you know how can I achieve this or do you have a different idea that will work? Please help! Thanks in advance.
It's kind of a broad implementation question since there are countless ways you could implement something like this.
If you are creating two collections, one with the buttons and one with the information, you potentially could just assign each of the buttons 'Tag' properties to point to the corresponding info and assign a generic OnClick event handler that displays the info.. something like:
infoControl.text = ((InfoClass)((Button)Sender.Tag)).pieceOfInformation;
But again there are many ways to do this, and the choice comes down to how you store your information.
For your first method, you could have a property of your custom control that is the index.
public class Box : Control
{
// ...existing code
private int index;
public int Index
{
get
{
return index;
}
set
{
index = value;
}
}
}
OR
For your second method, you could have a property of your custom control that is the additional info string.
public class Box : Control
{
// ...existing code
private string extraInfo;
public string ExtraInfo
{
get
{
return extraInfo;
}
set
{
extraInfo = value;
}
}
}
In either case, you could then access the proper information right in your click handler for the "box".
i don't know about the first way - got to noodle around more, but in the second way you can extended your custom or built-in control: for example:
public class ExtendedLabel: Label
{
public string[] MoreInfo { get; set; }
}
and initialize it
public TestForm()
{
InitializeComponent();
ExtendedLabel label = new ExtendedLabel();
label.MoreInfo = new string[] { "test" };
this.Controls.Add(label);
label.AutoSize = true;
label.Location = new System.Drawing.Point(120, 87);
label.Name = "label1";
label.Size = new System.Drawing.Size(35, 13);
label.TabIndex = 0;
label.Text = label.MoreInfo[0];
}
And later in your event handler you can use the inside information
How can you use a ListView to show the user a collection of objects, and to manage those objects?
For the purpose of argument, here's our design goal: We've got a "monster" object, and that "monster" will have several "powers." The user interacts with the powers via a ListView item.
First, we create a Power object. Give the object the following method:
public ListViewItem makeKey()
{
return new ListViewItem(name);
}
where name is the name of the power, and a string. This ListViewItem will serve as a key, allowing us to identify and retrieve this power later.
Next, we need to add somewhere in the Monster object to keep track of all these powers.
public Dictionary<ListViewItem,Power> powers;
So now we need a way to add powers to the monster.
public void addPower(Power newPower) {
ListViewItem key = newPower.makeKey();
monster.powers.add(key, newPower);
}
Ok, almost done! Now we've got a dictionary of ListViewItems which are tied to the monster's powers. Just grab the keys from that dictionary and stick them in a ListView:
foreach (ListViewItem key in powers.Keys)
powerList.Items.Add(key);
Where powerList is the ListView we're adding the ListViewItems to.
Alright, so we've got the ListViewItems in the ListView! Now, how do we interact with those? Make a button and then a function something like this:
private void powerRemoveButton_Click(object sender, EventArgs e)
{
if (powerList.SelectedIndices.Count > 0)
{
int n = powerList.SelectedIndices[0];
ListViewItem key = powerList.Items[n];
monster.powers.Remove(key);
powerList.Items.Remove(key);
}
else
{
MessageBox.Show("No power selected.");
}
}
And that's that. I hope you've found this helpful. I'm not sure if this was an intentional aspect of their design, but ListViews and Dictionaries blend together so amazingly well when you use a ListViewItem as a key that it's a joy!