I'm currently trying to read a xml file and add a control for every "Mods" entry.
<Modlist>
<Mods>
<Mod>Test1</Mod>
<Version>1.0</Version>
</Mods>
<Mods>
<Mod>Test2</Mod>
<Version>2.0</Version>
</Mods>
<Mods>
<Mod>Test3</Mod>
<Version>3.0</Version>
</Mods>
</Modlist>
Basically i want to add a control to a panel for every listed mod in the xml.
XDocument Mods = XDocument.Load(#"C:\dataset.xml");
foreach (var mod in Mods.Descendants("Mods"))
{
Button modbutton = new Button();
modbutton.Text = mod.Element("Mod").Value;
panel1.Controls.Add(modbutton);
}
Its working, but its only creating one button and seems to stop.
In my example it should create 3 buttons.
What do i have to change? Whats wrong with my code?
Your code to read xml is correct but you are putting each button one over the other. Set .Location property for every Button.
ur code working perfectly, but the problem is buttons are placed in same place. u need change the position.
Try this
XDocument Mods = XDocument.Load(#"C:\dataset.xml");
int I = 10;
foreach (var mod in Mods.Descendants("Mods"))
{
Button modbutton = new Button() { Top = 10 + I, Left = 10 };
modbutton.Text = mod.Element("Mod").Value;
panel1.Controls.Add(modbutton);
I += 50;
}
Related
I am encountering a strange phenomenon: I have a WinForms application with four GroupBoxes, all four initially empty. I use this to track new followers/unfollowers on Twitter, planning on expanding its use once this functions properly.
It does work properly for new followers. For these I have a GroupBox called grpFollow, to which I add LinkLabels with the ScreenNames of my new followers like this:
var folTop = new Point(grpFollow.Left + 5, grpFollow.Top + 5);
lblFollowers.Text = Properties.Settings.Default.FollowersNow.Count.ToString();
lblFriends.Text = Properties.Settings.Default.FriendsNow.Count.ToString();
var ctr = 1;
foreach (var fol in newFollowers)
{
var kvp = LookupUser(fol);
if (string.IsNullOrEmpty(kvp.Key)) continue;
var linklabel = new LinkLabel()
{
Text = kvp.Value,
Width = 200,
Height = 15,
Location = folTop,
Visible = true,
Name = $"follbl{ctr}"
};
ctr++;
linklabel.Links.Add(0, linklabel.Width-1, $"https://twitter.com/{kvp.Key}");
linklabel.Click += Linklabel_Click;
grpFollow.Controls.Add(linklabel);
folTop.Y += 25;
}
LookupUser is just a function that passes the user id to the Twitter API and returns the name & screen_name of that user. Works fine, no problem. LinkLabels added nicely, no problem there either.
The trouble is with the other group boxes, e.g. the one for new friends:
folTop = new Point(grpFriends.Left + 15, grpFriends.Top + 15);
ctr = 1;
foreach (var fol in newFriends)
{
var kvp = LookupUser(fol);
if (string.IsNullOrEmpty(kvp.Key)) continue;
var llabel = new LinkLabel()
{
Text = kvp.Value,
Width = 200,
Height = 15,
Location = folTop,
Visible = true,
Name = $"frdlbl{ctr}"
};
ctr++;
llabel.Links.Add(0, llabel.Width - 1, $"https://twitter.com/{kvp.Key}");
llabel.Click += Linklabel_Click;
grpFriends.Controls.Add(llabel);
folTop.Y += 25;
}
As you can see, the logic is identical (because I want to extract this part to a separate method to avoid repetition). The location is set relative to the grpFriends group box, everything else is the same. Yet, the LinkLabel does not show, i.e. the second group box remains (visually) empty!
I have set a breakpoint to check what might go wrong. I single stepped through: the correct screen name is being retrieved, the location is correct, the control is added - but nothing ever shows up.
P.S: This code is in the RunWorkerCompleted method of a background worker, no further code is executed after this point.
Any idea why the Label isn't displayed?
Edit: I'll be damned!
I just changed the location of the grpFriends LinkLabel to 10,10: it appears, juuust clipping the lower border of my friends' group.
Now here is where this gets weird for me:
As you can see, the group has a Y value of 351. Point (10,10) should not even be in the box. So, it seems that the location is the culprit and the original code created the label outside the form.
Replacing grpFriends.Top as Y value with grpFriends.Top - grpFriends.Height got me closer. The LinkLabel is farther down from the top than I'd like but that's not so bad.
Very strange.
Okay, thanks to #raBinn I figured it out. The mistake here was me assuming, the LinkLabels needed a location relative to the Form. However, when adding them to the Controls collection of a GroupBox, they automatically assume a location relative to the GroupBox, not the Form.
So, my code is now basically the same for all four group boxes and looks like this:
PopulateGroup(newFollowers, grpFollow);
PopulateGroup(unFollow, grpLost);
PopulateGroup(newFriends, grpFriends);
PopulateGroup(unFriend, grpDitched);
And:
private void PopulateGroup(List<string> collPeople, GroupBox groupBox)
{
var folTop = new Point(12, 25);
foreach (var fol in collPeople)
{
var kvp = LookupUser(fol);
if (string.IsNullOrEmpty(kvp.Key)) continue;
var linklabel = new LinkLabel()
{
Text = kvp.Value,
Width = 200,
Height = 15,
Location = folTop
};
ctr++;
linklabel.Links.Add(0, linklabel.Width - 1, $"https://twitter.com/{kvp.Key}");
linklabel.Click += Linklabel_Click;
groupBox.Controls.Add(linklabel);
folTop.Y += 25;
}
}
So it doesn't really matter whether the group box is on the left or right, top or bottom of the form...
What i have: Big PictureBox (lets call it Pic_Map) on the form. A class Ore.cs, A List<Ore> ores; and a database that pulls the data and places it into the ores list.
Functionality: So, The functionality of this is i have a TextBox/Combobox and a Button. When i press the Button, it will loop through the ores list and Dynamically add PictureBoxes ontop of the Pic_Map based on TexBox/ComboBox being equal to the data (in this case Ore_Name).
Problem: This all works fine, but the problem is that when i add the PictureBoxes Dynamically, it only seems to add the last value on the ores list (Red circles on Pic_Map). so, it ends up showing only 1 PictureBox instead of lets say 3, since i have 3 value Names that match with the TextBox/ComboBox.
Question: How to get it to work like when i write/choose "Flame Stone" it looks on all the data that has "Flame Stone" in its name and add it (Instead of it adding only the last value from the list).
Code:
private void PopulateComboBoxByName()
{
PictureBox ore_Area = new PictureBox();
db.GetOre(); //Getting data and putting it into "ores" list
foreach (Ore ore in db.ores)
{
if (CBOX_Filter.SelectedItem.ToString() == ore.Ore_Name)
{
int area_Width = Convert.ToInt32(ore.Area_Width);
int area_Height = Convert.ToInt32(ore.Area_Height);
int ore_Width = Convert.ToInt32(ore.Ore_Width);
int ore_Height = Convert.ToInt32(ore.Ore_Height) - area_Height / 2;
ore_Area.Name = "ore_Area";
ore_Area.ImageLocation = #"Data\Images\Circle.png";
ore_Area.SizeMode = PictureBoxSizeMode.StretchImage;
ore_Area.Size = new Size(Convert.ToInt32(area_Width), Convert.ToInt32(area_Height));
ore_Area.Location = new Point(Convert.ToInt32(ore_Width), Convert.ToInt32(ore_Height));
ore_Area.BackColor = Color.Transparent;
this.Controls.Add(ore_Area);
}
}
ore_Area.Parent = PIC_Map;
}
Images:
Data:
Map:
Thanks to LarsTech, it has been fixed.
Making the picturebox is moved inside the loop, this.controls.add is changed to PIC_Map.controls.add and Ore_Area.Parent = PIC_Map; is deleted.
I am trying to dynamically create a new button for each line of a text file.
My problem is that no matter how many lines the text file has, it only ever generates a single button.
The code:
System.IO.StreamReader file = new System.IO.StreamReader
(#"D:\SupportDash\Settings\Settings.txt");
string[] lines = System.IO.File.ReadAllLines(#"D:\SupportDash\Settings\Settings.txt");
foreach(String row in lines)
{
Button Buttona = new System.Windows.Forms.Button();
Buttona.Text = "Test";
Buttona.UseVisualStyleBackColor = true;
Buttona.Location = new System.Drawing.Point(85,28);
Buttona.Click += (s, e) =>
{
Form DynamicForm = new Form();
DynamicForm.Show();
};
groupBox2.Controls.Add(Button);
counter++;
}
file.Close();
}
I've also tried using a while and a do-while loop. -The same thing happens.
My text file is separated by a carriage return. (Its generated in-program using File.ApendAllText();)
Is it a problem being caused by my program only thinking there is one huge line?
You are putting all buttons at the same Location, so it may appear there is only one button, when in fact there is one button per line, they are just all on top of each other.
Try incrementing the Location's Top every time through the loop or use a panel control that supports wrapping.
you will need to position each new button at a new position for example
where your setting
Buttona.Location = new System.Drawing.Point(85,28);
call something like
var buttonHeight = 10;
Buttona.Location = new System.Drawing.Point(85,28 + (count * buttonHeight ));
you are actually creating multiple buttons but they are all on top of each other.
I'm trying to build a form application in Visual Studio 2010 using C#.
The program will be reading a excel file that contains a list of filenames, and will dynamically generate textbox for each filename.
Below is my code, just for clarification. I wanted to make the label a link to the file, that's why I didn't use checkboxes[i].Text = filename
CheckBox[] checkboxes = new CheckBox[fileCount];
Label[] labels = new Label[fileCount];
for (int i = 0; i < fileCount; i++ )
{
//creating a checkbox
checkboxes[i] = new CheckBox();
checkboxes[i].Location = new Point(360, (145 + i * 30));
checkboxes[i].Name = String.Format("checkbox{0}", i.ToString());
this.Controls.Add(checkboxes[i]);
//creating filename label
labels[i] = new Label();
labels[i].Location = new Point(20, (150 + i * 30));
labels[i].Text = existingFiles[i];
labels[i].Width = 330;
this.Controls.Add(labels[i]);
}
Say if fileCount equals to 100, it will make the form really big/long and won't be able to fit properly on most monitors.
Is there a way to make all dynamically generated checkboxes and labels all grouped in a area and just have the user be able to scroll? Something like a panel with scrolling? I don't know if there's anything like that.
I thought about using CheckedListBox, but doing that way I won't be able to make the filename a link. I want the user be able to click on the label and the file will be opened automatically, instead of selecting it.
Any help is appreciated!
Most controls have the AutoScroll property. Set this to true, and the control will automatically add a scrollbar when necessary. You can use the Panel control and add all of your links/checkboxes to that (if you don't want your whole form to scroll).
I read this topic (Adding buttons to a TabControl Tab in C#) but I don't figure out why my code below add one button only to the tabpage.
I've obviously debugged that the foreach works properly.
foreach (string line in File.ReadAllLines(#"C:\quicklauncher.ini"))
{
TabPage page = new TabPage(foldername);
DirectoryInfo d = new DirectoryInfo(line);
foreach (FileInfo file in d.GetFiles("*.*"))
{
Button button = new Button();
button.Text = file.Name;
button.Click += new EventHandler(button_Click);
page.Controls.Add(button);
}
tabControl.TabPages.Add(page); //add our tab page to the tab control
}
Thanks,
Steve
You thought it added only 1 button for you but in fact it did not, it added all the buttons for you but those buttons had the same Location (which is (0,0) by default). That's why you did think there was only 1 button (because you saw only 1 last button on top of others).
You added buttons automatically to your tabpage, so you should have some rule to locate them, I'm not sure what that rule is but I suppose you want to line them up vertically (just an example), I'm going to correct your code to achieve such a thing, at least you will see it work, and in fact all the buttons are added normally:
//you need some variable to save the next Top for each new button:
//let's call it nextTop:
int nextTop = 0;
foreach (FileInfo file in d.GetFiles("*.*"))
{
Button button = new Button { Top = nextTop,
Text = file.Name };
button.Click += new EventHandler(button_Click);
page.Controls.Add(button);
nextTop += button.Height + 5; //it's up to you on the
//Height and vertical spacing
}
//...
You can also try using some layout control like FlowLayoutPanel and TableLayoutPanel to contain all the buttons, they can help arrange your buttons in some way you may want, just try it.