I've been trying to figure out why my imageList won't render out my images when my form runs, I am using the following code...
public void renderImageList()
{
int selection = cboSelectedLeague.SelectedIndex;
League whichLeague = (League)frmMainMenu.allLeagues[selection];
string index = cboSelectedLeague.SelectedItem.ToString();
if (whichLeague.getLeagueName() == index)
{
foreach (Team t in allTeams)
{
Image teamIcon = Image.FromFile(#"../logos/" + t.getTeamLogo());
imgLstIcons.Images.Add(teamIcon);
}
}
else
{
MessageBox.Show("Something went wrong..." + whichLeague.getLeagueName() + " " + index + ".");
}
}
The method is fired when the user changes the index of my combo box, I know the program gets the correct path as I used a message box to display the path each path returned as I expected it to.
Am I missing something from my code to draw the image to the box?
Alex.
After adding all images to the ImageList, you should add all the items to the ListView as well:
for (int j = 0; j < imgLstIcons.Images.Count; j++)
{
ListViewItem item = new ListViewItem();
item.ImageIndex = j;
lstView.Items.Add(item);
}
source: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/876b6517-7306-44b0-88df-caebf3b1c10f/
You can also use a FlowLayoutPanel and dynamically create PictureBox elements, one for each Image, and not use ImageLists and ListViews at all. It depends on the type of UI you want.
Related
I want to create labels that will follow one another. I have a grid name WordTemplateLayout to which I want to add the labels. I add them dynamically on the wpf window constructor after InitializeComponent() is called. Here is the method creating the labels:
private void CreateWordTemplate()
{
IList<char> template = CurrentGame.Template;
double widthPerBox = WordTemplateLayout.Width / template.Count;
//template.Count being a number, irrelevant to the question
for (int i = 0; i < template.Count; i++)
{
var templateVisual = new Label();
templateVisual.Name = "c" + i;
templateVisual.Width = widthPerBox;
templateVisual.Height = WordTemplateLayout.Height;
templateVisual.Background = new SolidColorBrush(Colors.Aqua);
WordTemplateLayout.Children.Add(templateVisual);
}
}
the problem being, that what actually appends is that instead of the labels lining up one after the other, they overlap each other:
The aqua box is all the labels overlap each other
so what I am asking, is how can I make the labels line up (horizontally) instead of to overlap?
As others have pointed out, you're better off using a StackPanel, or learning how to use viewmodels and data binding. Having said that, to answer your direct question, here's how you'd do it programmatically.
**NOTE: Ignore the 5 that I'm passing in to the methods, and instead use your template.Count. This is was just for me to get it to work on my end.
public MainWindow()
{
InitializeComponent();
CreateGridLayout(5);
CreateWordTemplate(5);
}
// Define the Grid layout
// If you want the labels to follow one another horizontally, define columns.
// If you want them stacked vertically, instead define rows.
private void CreateGridLayout(int count)
{
for (int i = 0; i < count; i++)
{
WordTemplateLayout.ColumnDefinitions.Add(new ColumnDefinition());
}
}
private void CreateWordTemplate(int count)
{
double widthPerBox = WordTemplateLayout.Width / 5;
for (int i = 0; i < 5; i++)
{
var templateVisual = new Label();
templateVisual.SetValue(Grid.ColumnProperty, i); // SET YOUR COLUMN HERE!
templateVisual.Name = "c" + i;
templateVisual.Width = widthPerBox;
templateVisual.Height = WordTemplateLayout.Height;
templateVisual.Background = new SolidColorBrush(Colors.Aqua);
templateVisual.Content = templateVisual.Name;
WordTemplateLayout.Children.Add(templateVisual);
}
}
you need to use another layout so the new elements will get in normal order. try stackPanel.
you can use grid and give each new label Row=index.
you can give each new label margin, like newLabel.margin-top = index*50
I have a little problem, I'm trying update my listView(listClients)
private ListView initializeLstView()
{
var lstView = new ListView();
var lstViewItem = new ListViewItem();
for (uint i = 0; i < 18; ++i)
{
lstViewItem = lstView.Items.Add("Free");
lstViewItem.SubItems.Add("Free");
}
return (lstView);
}
private ListView setNamesToLstView()
{
var lstView = initializeLstView();
try
{
for (uint i = 0; i < 18; ++i)
{
lstView.Items[(int)i].Text = clients.GetName(i);
lstView.Items[(int)i].SubItems[1].Text = "{" + i.ToString() + "}";
}
lstView.Update();
}
catch (Exception a)
{
Interaction.MsgBox(a.ToString());
}
return (lstView);
}
private void btnRefreshClients_Click(object sender, EventArgs e)
{
listClients = setNamesToLstView(); // Here, no update
}
But here, my listView contains nothing, no update / no refresh, why ?
How can I resolve this ?
The problem is you are adding items to another list view.
listClients is a member variable which points to a ListView which you previously added to Controls collection of your form. When you want to add items to that list view, you should add items exactly to that object using listClients.Items.Add(...).
But currently you have created a ListView in the method and added items to it and at last returned it and assigned it to listClients. It doesn't make your new created list view be shown on your form. It makes listClients variable only points to new created control, Whilst you are seeing the previous created ListView.
Is it possible to set a components visible attribute based on its name?
I have 12 "master" components (comboboxes) if you want to call them that and based on the selection in these I want to display anywhere from 1 to 16 textboxes. These are named in numeric order such as combobox1_textbox_0, combobox1_textbox_1 and so on. What I would like to do ideally is take the index of the combobox and pass it as a parameter to a method that sets the textboxes visible attribute to visible/hidden depending on the index passed into the method.
Is this possible? in pseudocode or what you call it I would like it to work something like this:
private void methodToSetVisibleAttribute(int indexFromMainComboBox)
{
for(int i = 0; i < 15; i++)
{
if(i < index)
{
combobox1_textbox_+i.Visible = true;
}
else
{
combobox1_textbox_+i.Visible = false;
}
}
}
I could do panels or something for the choices but seeing as all the selections from the combobox will use the same textboxes but in different amounts it seems like alot of work to make a panel for every possible selection not to mention difficult to expand the program later on.
Assuming you are using Windows Forms and not WPF, you can use ControlCollection.Find() to find controls by name:
var textBox = this.Controls.Find(string.Format("combobox1_textbox_{0}", i), true).OfType<ComboBox>().FirstOrDefault();
if (textBox != null)
textBox.Visible = (i < index);
else
Debug.Assert(false, "textbox not found"); // Or throw an exception if you prefer.
I'll suggest an alternative to your approach, maybe not quite what you're looking for:
Place your combo boxes in a List<ComboBox> and you can access them by an index number.
List<ComboBox> myCombos = new List<ComboBox>();
for (int i = 0; i < 16; i++)
{
ComboBox cb = new ComboBox();
//do what ever you need to do here. Set its location, add items, etc.
Form1.Controls.Add(cb); //Alternatively add it to another container.
myCombos.Add(cb); //Now it's in a list.
}
Modify them like this:
for(int i = 0; i < 15; i++)
{
if(i < index)
{
myCombos[i].Visible = true;
}
else
{
myCombos[i].Visible = false;
}
}
Or even more succintly:
for(int i = 0; i < 15; i++)
{
myCombos[i].Visible = i < index;
}
Im trying to Create a method that can look at all text boxes in my program and tell me when the next blank one is so far. this is what i have come up with and cannot get it to work
public void CheckBox()
{
string[] itemBoxArray = new string[] { "itemBox1", "itemBox2", "itemBox3", "itemBox4", "itemBox5", "itemBox6",
"itemBox7", "itemBox8", "itemBox9", "itemBox10","itemBox11","itemBox12","itemBox13","itemBox14","itemBox15","itemBox16",};
for (int i = 0; i < itemBoxArray.Length; i++)
{
if (itemBoxArray[i] == string.Empty)
{
MessageBox.Show(" " + itemBoxArray[i] + " Is empty");
}
else
{
MessageBox.Show("Item Box is full");
}
}
}
create array of TextBox like below
public void CheckBox()
{
TextBox[] itemBoxArray = new TextBox[] { itemBox1, itemBox2, ........};
for (int i = 0; i < itemBoxArray.Length; i++)
{
if (String.IsNullOrEmpty(itemBoxArray[i].Text))
{
MessageBox.Show(" " + itemBoxArray[i].Name + " Is empty");
}
else
{
MessageBox.Show("Item Box is full");
}
}
}
You could use something like this to find the first TextBox that has an empty Text value:
var emptyTextBox = Controls.OfType<TextBox>().First(x => x.Text == string.Empty);
MessageBox.Show(string.Format(" {0} Is empty", emptyTextBox.Name));
You'll probably have to beef this up a bit.
It'll fail if no TextBox is empty. Use FirstOrDefault and test for null if that's a concern.
Also, it'll fail to find TextBox controls inside of a GroupBox or Panel. That may not matter depending on how your form is designed.
If you only have a set number of TextBox controls to check for, your code will work with a little adjustment, but if you're going to keep adding more TextBoxes, it's going to be a pain to maintain.
I am in a beginning C# class and I am having trouble figuring out why after the following code runs, the selected index is still -1 (i.e. the combobox at load is empty). It should be defaulting to selectedIndex = 1:
public string[,] GetArray()
{
//create array with conversion values
string[,] conversionInfo = { {"Miles","Kilometers", "1.6093"},
{"Kilometers","Miles", ".6214"},
{"Feet","Meters", ".3048"},
{"Meters","Feet","3.2808"},
{"Inches","Centimeters", "2.54"},
{"Centimeters","Inches",".3937"}};
return conversionInfo;
}
private void Form_Load(object sender, EventArgs e)
{
//get array to use
string[,] conversionChoices = GetArray();
//load conversion combo box with values
StringBuilder fillString = new StringBuilder();
for (int i = 0; i < conversionChoices.GetLength(0); i++)
{
for (int j = 0; j < conversionChoices.GetLength(1) - 1; j++)
{
fillString.Append(conversionChoices[i, j]);
if (j == 0)
{
fillString.Append(" to ");
}
}
cboConversion.Items.Add(fillString);
fillString.Clear();
}
//set default selected value for combobox
cboConversion.SelectedIndex = 0;
}
public void cboConversions_SelectedIndexChanged(object sender, EventArgs e)
{
LabelSet(cboConversion.SelectedIndex);
}
public void LabelSet(int selection)
{
//get array to use
string[,] labelChoices = GetArray();
//set labels to coorespond with selection
string from = labelChoices[selection, 0];
string to = labelChoices[selection, 1];
lblFrom.Text = from + ":";
lblTo.Text = to + ":";
}
This is a class assignment so I am not allowed to set anything using the designer, other than to link methods to event. Everything works correctly except for the default for the combobox.
Your code is completely correct, but you have one single fault in your mind. Consider, that you are loading the items into the ComboBox after you have initialized the control. At this point the control have no items, therefore the property "Text" is not setted automatically.
You have to differ between the SelectedIndex, which is the index of the item in the list of items, and the Text, which is the text, shown in the ComboBox. So think about when and how you should set the Text-property of the ComboBox.
Always set the Text-property to the first value of your item-list, after you changed it.
Greetings,
the answer of Mario can be interpreted also as:
put your code after the loading (example: on the shown event), in this way the control is initialized and has items.