my code dynamically adding ListBoxes, which contains buttons. Buttons dynamically addind another buttons. Well... thats expectation. My code doesn't works.
Here is my code:
public Button createElements(string nameOfElement)
{
if (nameOfElement.Contains("Floor"))
{
// code creating Button
return floorButton;
}
else if (nameOfElement.Contains("Sound"))
{
// code creating Button
return soundButton;
}
else if (nameOfElement.Contains("Add"))
{
// code creating Button
return addButton;
}
return null;
}
private ListBox addNewListBox(ListBox targetElement, int ex)
{
// vytvori ListBox do hlavniho ListBoxu
ListBox elementListBox = new ListBox();
elementListBox.Name = "elementListBox" + indexY;
elementListBox.VerticalAlignment = VerticalAlignment.Top;
elementListBox.ItemsPanel = (ItemsPanelTemplate)XamlReader.Parse("<ItemsPanelTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"><StackPanel Orientation=\"Horizontal\"/></ItemsPanelTemplate>");
if (ex == 1)
{
targetElement.Items.Remove(addFloor);
targetElement.Items.Add(elementListBox);
elementListBox.Items.Add(createElements("Floor"));
elementListBox.Items.Add(createElements("Sound"));
elementListBox.Items.Add(createElements("Add"));
targetElement.Items.Add(addFloor);
indexY++;
indexX = 0;
}
return elementListBox;
}
Here is detail of final function.
private void putElements(ListBox targetElement, Button targetObject)
{
targetElement.Items.Add(targetObject);
// there's problem
MessageBox.Show("targetElement: ", targetElement.Name);
MessageBox.Show("targetObject", targetObject.Name);
}
Click event calling this function:
putElements(addNewListBox(mainListBox, 0), createElements("Sound"));
MessageBoxes prints names of objects in last function. Objects are right, but this line:
targetElement.Items.Add(targetObject);
there is problem - this line doing nothing..
Thanks for help!!
You're just adding the new ListBox to your mainListBox if the ex-value is 1, but in your case it's 0.
So your new ListBox (targetElement in putElements-method) will never be added to your mainListBox and hence not displayed. Thats why targetElement.Items.Add(targetObject); seems to not work.
Related
Background
I have a main form that has a tableLayoutPanel. Within that I have three panel, a header, footer and left side bar. In the remaining space I add and remove usercontrols this one in the example is called ctrlmanagepreset.
Within these usercontrols I have controls. Namely a Listsbox s, that i'm trying to add items too.
I am getting the items from an xml file that does contain items and reading them in to an object list. The name of each object is then added to the listbox.
All of the Controls are accessable as I've made them public. I think it might be due to the way i create and add them?
Question
Why aren't the Listboxes updating, showing the added items?
Code
Button click event that creates usercontrol
public void btnManage_Click(object sender, EventArgs e)
{
tableLayoutPanel.Controls.Add(new ctrlManagePresets () { Dock = DockStyle.Left }, 1, 1);
PopulateCreateJob();
}
Method that Populates Listbox
public void PopulateCreateJob()
{
ctrlManagePresets ctrlmanagepresets = new ctrlManagePresets();
//read in contents of xml file
if (File.Exists(JoblistXmlFilepath))
{
XmlSerializer deserializer = new XmlSerializer(typeof (List<Favourite>));
TextReader reader = new StreamReader(JoblistXmlFilepath);
//create list of old fave objects
var xmlList = (List<Favourite>) deserializer.Deserialize(reader);
reader.Close();
if (xmlList.Count > 0)
{
foreach (Favourite t in xmlList)
{
//add favourite objects to combobox
try
{
ctrlmanagepresets.lbCreateJob.Items.Add(t.Name);
}
catch
{
MessageBox.Show(#"There is an object with no name in the XML.", #"Message",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
ctrlmanagepresets.lbCreateJob.Refresh();
}
else
{
ctrlmanagepresets.lbCreateJob.Items.Add(#"Settings File Not Found");
ctrlmanagepresets.lbCreateJob.Enabled = false;
ctrlmanagepresets.lbCreateJob.BackColor = Color.DarkRed;
}
}
You are not adding the items to the instance of the control that you add to your tableLayoutPanel.
Just make your PopulateCreateJob return the instance that is built and intialized with the xml data
public void btnManage_Click(object sender, EventArgs e)
{
ctrlManagePresets ctrl = PopulateCreateJob();
ctrl.Dock = DockStyle.Left;
tableLayoutPanel.Controls.Add(ctrl, 1, 1);
}
public ctrlManagePresets PopulateCreateJob()
{
ctrlManagePresets ctrlmanagepresets = new ctrlManagePresets();
// current code that initialize the instance of your control
....
// return the control instance initialized to the caller
return ctrlmanagepresets;
}
I have implemented a custom contextual action bar with two buttons : one for deleting selected items from a listview and the other one for editing selected item . What I am trying to do is to make the editButton invisible when two or more items have been selected. I tried doing it this way but nothing happens:
public void OnItemCheckedStateChanged (ActionMode mode, int position, long id, bool check)
{
SetSubtitle (mode);
if (listview.CheckedItemCount > 1) {
disableButtonFlag = true;
} else
disableButtonFlag = false;
self.InvalidateOptionsMenu();
}
public bool OnCreateActionMode (ActionMode mode, IMenu menu)
{
self.MenuInflater.Inflate (Resource.Menu.CAB_menu, menu);
if (disableButtonFlag) {
menu.FindItem(Resource.Id.action_edit).SetVisible(false);
} else {
menu.FindItem(Resource.Id.action_edit).SetVisible(true);
}
mode.Title = "Select Items";
SetSubtitle (mode);
return true;
}
This is how handling multiple items works for me:
private void listView_SelectedIndexChanged(object sender, EventArgs e)
{
if(listView.SelectedIndices.Count > 1)
{
MessageBox.Show("Multiple rows selected!");
}
}
If selected index changes, check for how many indices are checked. If more than 1 (=multiple), fire your code.
Finally I found my mistake! It was that instead of declaring:
if (listview.CheckedItemCount > 1) {
disableButtonFlag = true;
} else
disableButtonFlag = false;
within my OnCreateActionMode method and calling Activity.InvalidateOptionsMenu() in my OnItemCheckedStateChanged()method I should have declared these rows within my OnPrepareActionMode() method and then called ActionMode.Invalidate() within the OnItemCheckedStateChanged()method.
Please forgive me for such a stupid question. I am sure many of you will find this easy, where I have sent almost half the day reading trying to figure this out.
Here is the problem:
I have a FORM (Form1.cs) made. In that form I created a listview, and named it "ListView1".
Within the Form1.cs, I call a function called FileManager(this), where I pass in the THIS object.
In FileManager.cs I was able to listviewArray= originalForm.Controls.Find("listView1", true) and find that 'listview'.
When I do a listviewArray[0]<-- I can't seem to add a list to it.
FileManager.cs
FileManager(object sender)
{
if (sender != null)
{
originalForm = (Form)sender;
}
}
public void getFiles()
{
filePaths = Directory.GetFiles(hsocDir);
if(filePaths != null)
{
listviewArray= originalForm.Controls.Find("listView1", true);
if(listviewArray != null)
{
ListViewItem lvi = new ListViewItem("text");
// My Array is listViewArray
// How to add things to Lvi to it.
}
}
== Form1.cs
public Form1()
{
InitializeComponent(`enter code here`);
mysql = new MySQLCheck(this);
fileManager = new FileManager(this);
fileManager.getFiles();
}
You can't access element 0 of the collection because the collection is empty. To add an item, use:
listViewArray.Items.Add(lvi);
You need to modify the Items collection instead of the ListView itself for this to work, as ListView is not a collection (its a control).
listViewArray.Items.Add(lvi);
Also in your listview,setting this properties will help :
// Set the view to show details.
listViewArray.View = View.Details;
// Select the item and subitems when selection is made.
listViewArray.FullRowSelect = true;
// Display grid lines.
listViewArray.GridLines = true;
I have a BindingList< KeyValuePair < string, string > > that is bound to a ComboBox control. Based on some conditions, the BindingList will be added a new KeyValuePair. Now, the Newly added item shows up at index 0 of the Combobox, instead of at the end.
While debugging, I found that the BindingList has got the right order. (i.e, the new KeyValuePair is appended)
Also, I check the SelectedValue of the ComboBox in it's SelectedIndexChanged handler and it seems to be not of the ListItem that got selected. Instead, it is that of the supposed ListItem, if the ComboBox had got the right order as in its DataSource, - the BindingList..
The code is a small part of a large project.. Plz let me know if the question is not clear. I can put the relevant parts of the code as per our context.
How could something like this happen? What can I do differently?
I have this class something like this.
public class DropdownEntity
{
//removed all except one members and properties
private string frontEndName
public string FrontEndName
{
get {return this.frontEndName; }
set {this.frontEndName= value; }
}
//One Constructor
public DropdownEntity(string _frontEndName)
{
this.FrontEndName = _frontEndName;
//Removed code which initializes several members...
}
//All methods removed..
public override string ToString()
{
return frontEndName;
}
}
In my windows form, I have a tab control with several tabs. In one of the tabs pages, I have a DataGridView. The user is supposed to edit the cells and click on a Next - button. Then, some processing will be done, and the TabControl will be navigated to the next tab page.
The next tab page has the combobox that has the problem I mentioned. This page also has a back button, which will take back.. the user can modify the gridview cells again.. and click on the next button. This is when the order gets messed up.
I am posting here the Click event handler of the Next Button.. Along with the class, with the rest of the code removed.
public partial class AddUpdateWizard : Form
{
//Removed all members..
BindingList<KeyValuePair<string, string>> DropdownsCollection;
Dictionary<string, DropdownEntity> DropdownsDict;
//Defined in a partial definition of the class..
DataGridView SPInsertGridView = new DataGridView();
ComboBox DropdownsCmbBox = new ComboBox();
Button NextBtn2 = new Button();
Button BackBtn3 = new Button();
//Of course these controls are added to one of the panels
public AddUpdateWizard(MainForm mainForm)
{
InitializeComponent();
DropdownsDict = new Dictionary<string, DropdownEntity>();
}
private void NextBtn2_Click(object sender, EventArgs e)
{
string sqlArgName;
string frontEndName;
string fieldType;
for (int i = 0; i < SPInsertGridView.Rows.Count; i++)
{
sqlArgName = "";
frontEndName = "";
fieldType = "";
sqlArgName = SPInsertGridView.Rows[i].Cells["InsertArgName"].Value.ToString().Trim();
if (SPInsertGridView.Rows[i].Cells["InsertArgFrontEndName"].Value != null)
{
frontEndName = SPInsertGridView.Rows[i].Cells["InsertArgFrontEndName"].Value.ToString().Trim();
}
if (SPInsertGridView.Rows[i].Cells["InsertArgFieldType"].Value != null)
{
fieldType = SPInsertGridView.Rows[i].Cells["InsertArgFieldType"].Value.ToString().Trim();
}
//I could have used an enum here, but this is better.. for many reasons.
if (fieldType == "DROPDOWN")
{
if (!DropdownsDict.ContainsKey(sqlArgName))
DropdownsDict.Add(sqlArgName, new DropdownEntity(frontEndName));
else
DropdownsDict[sqlArgName].FrontEndName = frontEndName;
}
else
{
if (fieldType == "NONE")
nonFieldCount++;
if (DropdownsDict.ContainsKey(sqlArgName))
{
DropdownsDict.Remove(sqlArgName);
}
}
}
//DropdownsCollection is a BindingList<KeyValuePair<string, string>>.
//key in the BindingList KeyValuePair will be that of the dictionary.
//The value will be from the ToString() function of the object in the Dictionary.
DropdownsCollection = new BindingList<KeyValuePair<string,string>>(DropdownsDict.Select(kvp => new KeyValuePair<string, string>(kvp.Key, kvp.Value.ToString())).ToList());
DropdownsCmbBox.DataSource = DropdownsCollection;
DropdownsCmbBox.DisplayMember = "Value";
DropdownsCmbBox.ValueMember = "Key";
//Go to the next tab
hiddenVirtualTabs1.SelectedIndex++;
}
private void BackBtn3_Click(object sender, EventArgs e)
{
hiddenVirtualTabs1.SelectedIndex--;
}
//On Selected Index Changed of the mentioned Combobox..
private void DropdownsCmbBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropdownsCmbBox.SelectedValue != null)
{
if (DropdownsDict.ContainsKey((DropdownsCmbBox.SelectedValue.ToString())))
{
var dropdownEntity = DropdownsDict[DropdownsCmbBox.SelectedValue.ToString()];
DropdownEntityGB.Text = "Populate Dropdowns - " + dropdownEntity.ToString();
//Rest of the code here..
//I see that the Datasource of this ComboBox has got the items in the right order.
// The Combobox's SelectedValue is not that of the selected item. Very Strange behavior!!
}
}
}
}
The very first time the user clicks the Next Button, it's fine. But if he clicks the Back Button again and changes the Data Grid View cells.. The order will be gone.
I know, it can be frustrating to look at. It's a huge thing to ask for help. Any help would be greatly appreciated!
Please let me know if you need elaboration at any part.
Thanks a lot :)
I think you have two problems here.
First, if you want to retain the order of the items you should use an OrderedDictionary instead of a regular one. A normal collection will not retain the order of the items when you use Remove method. You can see more info about this related to List here.
You could use such dictionary like this:
DropDownDict = new OrderedDictionary();
// Add method will work as expected (as you have it now)
// Below you have to cast it before using Select
DropDownCollection = new BindingList<KeyValuePair<string, string>>(DropDownDict.Cast<DictionaryEntry>().Select(kvp => new KeyValuePair<string, string>(kvp.Key.ToString(), kvp.Value.ToString())).ToList());
The second problem could be that you change the display name (FrontEndName) of already existing items, but the key is preserved. When you add a new item, try to remove the old one that you're not using anymore and add a new item.
The Sorted Property of the Combobox is set to True! I didn't check that until now. I messed up. Terribly sorry for wasting your time Adrian. Thanks a lot for putting up with my mess here.. :)
When I change the datasource of my Listbox all items are cleared, when loading new data into this Listbox it stays clear.
I have another ListBox right new to this one with the same refresh code but that one refreshes perfectly.
private void RefreshContacts()
{
this.ListContacts.DataSource = null;
this.ListContacts.DataSource = this.contacts;
this.BoxCountContacts.Text = this.ListContacts.Items.Count.ToString();
}
Anyone have an idea how to fix the listbox from being cleared and bugged?
Here is the full refresh codes of the two listboxes
private Contact[] contacts, feed; private Boolean isFeed;
internal ArcFeed()
{
this.InitializeComponent();
this.contacts = this.feed = new Contact[0];
}
private void RefreshForm(Boolean isFeed)
{
if (isFeed)
{
this.RefreshFeed();
}
else
{
this.RefreshContacts();
}
}
private void RefreshContacts()
{
this.ListContacts.DataSource = null;
this.ListContacts.DataSource = this.contacts;
this.BoxCountContacts.Text = this.ListContacts.Items.Count.ToString();
}
private void RefreshFeed()
{
this.ListFeed.DataSource = null;
this.ListFeed.DataSource = this.feed;
this.BoxCountFeed.Text = this.ListFeed.Items.Count.ToString();
}
private void OpenFile()
{
if (this.isFeed)
{
this.BoxFileFeed.Text = this.DialogOpen.FileName;
this.feed = ArcBuzz.Load(this.DialogOpen.FileName);
}
else
{
this.BoxFileContacts.Text = this.DialogOpen.FileName;
this.contacts = ArcBuzz.Load(this.DialogOpen.FileName);
}
this.RefreshForm(this.isFeed);
}
All code is debugged and follows it's course properly, I don't see any errors, the correct listbox's datasource are set and changed.
Just to make sure, have you checked that there are actually items in the contacts collection?
Also, if you've got two Listboxes, double check that you are using the right Listbox in each of the refresh code sections.
Sounds stupid, but its silly mistakes like this that get overlooked a lot of the time. With databinding its usually something small like this stopping it working.