Run time adding control in C# - c#

I am making an application in which I want to add buttons on panel from my main form dynamically. If I have 10 items in List then that many buttons will be generate on panel from main form. But when I try to do that one then it shows me error that Control.Invoke required.
Please anyone suggest me how to add controls...??
private void CheckOrderListEntry(Workorder workorder)
{
int ticketID = workorder.TicketID;
int index = 0;
int lastIndex = _workorderList.Count;
bool isExist = false;
for (index = 0; index < lastIndex; index++)
{
int existingTicektId = _workorderList[index].TicketID;
if (ticketID == existingTicektId)
{
_workorderList[index] = workorder;
isExist = true;
break;
}
}
if (!isExist)
{
_workorderList.Add(workorder);
}
ListEventChangeHandler();
}
public void ListEventChangeHandler()
{
_orderBtn = new Button[_workorderList.Count];
int index = 0;
int lastIndex = _orderBtn.Length;
for (; index < lastIndex; index++)
{
Workorder workorder = _workorderList[index];
_orderBtn[index] = new Button();
_orderBtn[index].Name = String.Format("{0}", index);
_orderBtn[index].Text = String.Format("Order #: {0} Source: {1} Desination: {2}", workorder.TicketID, workorder.PickupAddress, workorder.DropoffAddress);
_orderBtn[index].BackColor = Color.SteelBlue;
_orderBtn[index].ForeColor = Color.White;
_orderBtn[index].Font = new Font("Tahoma", 16, FontStyle.Regular);
_orderBtn[index].Click += new EventHandler(OrderBtnClick);
}
UpdatePanel(_orderBtn);
}
public delegate void UpdateAcceptOrderPanel(Button[] btn);
public void UpdatePanel(Button[] btn)
{
try
{
if (this.InvokeRequired)
{
UpdateAcceptOrderPanel updateMyPanel = new UpdateAcceptOrderPanel(UpdatePanel);
this.Invoke(updateMyPanel, btn);
}
else
{
AddButtonOnPanel(btn);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void AddButtonOnPanel(Button[] btn)
{
for (int index = 0; index < btn.Length; index++)
{
this.acceptOrderPanle.Controls.Add(btn[index]);
}
}

I'm not very good on delegates, but this is the way I would do your UpdatePanel method ...
public void UpdatePanel(Panel panel, Button button)
{
if(panel.InvokeRequired)
{
panel.Invoke(new Action<Panel,Button>(UpdatePanel), new object[] {panel, button});
}
else
{
panel.Controls.Add(button);
}
}
hope this help ...

Related

Windows Forms Button codes

I am trying to create/code for a search button in C# Forms.
This what I have so far:
private void btnSearch_Click(object sender, EventArgs e)
{
for (int i = 0; i < lstCustomerDB.Items.Count; i++)
{
string item = lstCustomerDB.Items[i].ToString();
if (item.Contains(txtSearch.Text))
{
index = 1;
}
}
lstCustomerDB.Items.Clear();
if (index < 0)
{
`enter code here` MessageBox.Show("Item not found.");
txtSearch.Text = String.Empty;
}
else
{
lstCustomerDB.SelectedIndex = index;
}
}
Any help would be grateful for! Thanks!
Using LINQ:
private void Search()
{
//Grab the first item that matches (or null if not found)
var firstMatch = lstCustomerDB.Items.Cast<string>()
.FirstOrDefault(x => x.Contains(txtSearch.Text));
if (firstMatch != null)
{
lstCustomerDB.SelectedItem = firstMatch;
}
else
{
MessageBox.Show("Item not found.");
txtSearch.Text = String.Empty;
}
}
Modifying your code:
int index = -1;
for (int i = 0; i < lstCustomerDB.Items.Count; i++)
{
string item = lstCustomerDB.Items[i].ToString();
if (item.Contains(txtSearch.Text))
{
index = i;
lstCustomerDB.SelectedIndex = index;
break;
}
}
if (index < 0)
{
MessageBox.Show("Item not found.");
txtSearch.Text = String.Empty;
}

Dynamically generating textboxes asp.net

I have created a function to dynamically create textboxes based on the amount selected from the textbox, additionally I'm using these textboxes to display data from database. However when the user chooses for exactly five from the dropdownlist, and three textboxes was already there, instead of adding 2 more textboxes, it adds the additional 5 textboxes. What I do in order to just add the additionaly textboxes?
protected void TotalSeal_SelectedIndexChanged(object sender, EventArgs e)
{
populate();
}
public void populate()
{
int count = Convert.ToInt32(TotalSeal.SelectedItem.Value);
for (int i = 0; i < count; i++)
{
if (i < 0)
{
}
else
{
TextBox tx = new TextBox();
tx.MaxLength = 10;
tx.Width = 100;
phSealNum.Controls.Add(tx);
phSealNum.Controls.Add(new LiteralControl(" "));
ControlCache.Add(tx);
}
}
}
UPDATE
public void populate()
{
//ControlCache = new List<Control>();
//phSealNum.Controls.Clear();
int targetCount = Convert.ToInt32(TotalSeal.SelectedItem.Value);
int currentItems = phSealNum.Controls.OfType<TextBox>().Count();
int totalitems = targetCount - currentItems;
if (totalitems <= 7)
{
for (int i = 0; i < totalitems; i++)
{
TextBox tx = new TextBox();
tx.MaxLength = 10;
tx.Width = 100;
phSealNum.Controls.Add(tx);
phSealNum.Controls.Add(new LiteralControl(" "));
ControlCache.Add(tx);
}
}
else
{
lblError.Text = targetCount + " exceeds number of seals";
}
}
Using #indrit-kello logic should be like this:
protected void TotalSeal_SelectedIndexChanged(object sender, EventArgs e)
{
populate();
}
public void populate()
{
int targetCount = Convert.ToInt32(TotalSeal.SelectedItem.Value);
if(targetCount > 7)
targetCount = 7;
int currentItems = 0;//TODO
for (int i = currentItems; i < targetCount; i++)
{
TextBox tx = new TextBox();
tx.MaxLength = 10;
tx.Width = 100;
phSealNum.Controls.Add(tx);
phSealNum.Controls.Add(new LiteralControl(" "));
ControlCache.Add(tx);
}
}

System.argumentoutofrangeexception while invoke Listviewitems using iterators

I have an application which must contain the items in large quantities and continuously into listviews control:
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
deg_loadfile load = new deg_loadfile(loadfile);
load.BeginInvoke(new AsyncCallback(loadcallback),null);
}
void countfile() {
int listcount = listView1.Items.Count;
for (int x = 0; x < listcount; x++) {
listView1.BeginInvoke((MethodInvoker)delegate {
listView1.Items[x].SubItems[1].Text = "ok";
listView1.Items[x].SubItems[2].Text = "ok";
listView1.Items[x].SubItems[3].Text = "done";
},x);
}
}
void countcallback(IAsyncResult ae) {
MessageBox.Show("count finished");
}
delegate void deg_count();
void loadcallback(IAsyncResult ae) {
MessageBox.Show("finished");
}
delegate void deg_loadfile();
void loadfile() {
string file = File.ReadAllText("hughlist.txt");
string[] files = Regex.Split(file,"\n");
foreach (string str in files) {
listView1.BeginInvoke((MethodInvoker)delegate {
ListViewItem item = new ListViewItem(str);
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
listView1.Items.Add(item);
},str);
}
}
private void button2_Click(object sender, EventArgs e)
{
deg_count count = new deg_count(countfile);
count.BeginInvoke(new AsyncCallback(countcallback),null);
}
The code above throws system.argumentoutofrangeexception (please see image below)
link image: http://i.stack.imgur.com/WJ7sA.png
The iteration has exceeded the conditions that I have given, why did it happen (note:in my case, i must use "for" instead of "foreach" or other enumeration) ?
thx
UPDATE:
thx to #saruman for the answer (keyword is "access to modified closure"), i've updated the code as below
for (int x = 0; x < listcount; x++) {
var x1=x;
listView1.BeginInvoke((MethodInvoker)delegate
{
listView1.Items[x1].SubItems[1].Text = "ok";
listView1.Items[x1].SubItems[2].Text = "ok";
listView1.Items[x1].SubItems[3].Text = "done";
}, x1); }
Look up access to modified closure
Try this
var listcount = listView1.Items.Count;
for (var x = 0; x < listcount; x++)
{
var x1 = x;
listView1.BeginInvoke((MethodInvoker)delegate
{
listView1.Items[x1].SubItems[1].Text = "ok";
listView1.Items[x1].SubItems[2].Text = "ok";
listView1.Items[x1].SubItems[3].Text = "done";
});
}

CheckedListBox.SelectedItems.Count = 1?

In C#, I have checked list boxes, that I need to store the data in arrays, but when I start the event that writes the objects to the array, I have to set the size of the array, which I naturally set to the amount of items checked. However, the items checked, for both checked list boxes I have is 1, no matter how many I check. Can someone help?
public partial class Form3 : Form
{
public static object[] dtype;
public static bool loaded = false;
bool typeselecte = false;
bool typeselectd = false;
public Form3()
{
InitializeComponent();
}
private void Form3_Shown(object sender, EventArgs e)
{
if (loaded)
{
int counte = 0;
int countd = 0;
types1.Items.AddRange(dtype);
types2.Items.AddRange(dtype);
if (typeselecte)
{
for (int i = 0; i < types1.Items.Count; i++)
{
if (i == Form1.enumber[counte])
{
types1.SelectedItems[i] = Form1.esearch[i];
counte++;
}
}
}
if (typeselectd)
{
for (int j = 0; j < types2.Items.Count; j++)
{
if (j == Form1.dnumber[countd])
{
types2.SelectedItems[j] = Form1.dsearch[j];
countd++;
}
}
}
}
}
public void dtypes()
{
dtype = new object[types1.Items.Count];
for (int i = 0; i < types1.Items.Count; i++)
{
dtype[i] = types1.Items[i];
}
}
private void button1_Click(object sender, EventArgs e)
{
if (types1.SelectedItems.Count > 0)
typeselecte = true;
if (types2.SelectedItems.Count > 0)
typeselectd = true;
Form1.esearch = new object[types1.SelectedItems.Count];
Form1.dsearch = new object[types2.SelectedItems.Count];
Form1.enumber = new int[types1.SelectedItems.Count];
Form1.dnumber = new int[types2.SelectedItems.Count];
int counte = 0;
int countd = 0;
if (typeselecte)
{
for (int i = 0; i < types1.SelectedItems.Count; i++)
Form1.esearch[i] = types1.SelectedItems[i];
}
if (typeselectd)
{
for (int j = 0; j < types2.SelectedItems.Count; j++)
Form1.dsearch[j] = types2.SelectedItems[j];
}
if (typeselecte)
{
for (int k = 0; k < types1.Items.Count; k++)
{
if (Form1.esearch[k] == types1.Items[k])
{
Form1.enumber[counte] = k;
counte++;
}
else
{
k--;
}
}
}
if (typeselectd)
{
for (int l = 0; l < types2.Items.Count; l++)
{
if (Form1.dsearch[l] == types2.Items[l])
{
Form1.dnumber[countd] = l;
countd++;
}
else
{
l--;
}
}
}
this.Close();
}
}
Form1.esearch and dsearch are object arrays, which the size hasn't been picked yet, and e and dnumber are int arrays that have unknown size as well, I just didn't feel the need to put in that code.
I believe you need to use the property CheckedItems as opposed to SelectedItems.

Plugin another project in current window

I'm creating a WPF application with a menu, when clicked on menuItem I want to show NQueens (another project) in my Window (plugin). I've placed an NQueens.dll in my CurrentDirectory to work with. To make this work I've created an assembly object to load the classes and created an instance of Nqueens.Nqueen and invoked the methods.
The NQueens project consists of a class NQueen.cs and a MainWindow.
namespace NQueens
{
public class NQueen
{
public static bool berekenQueens(int Row, int N, bool[,] bord)
{
if (Row >= N) return true; //stopconditie
for (int Col = 0; Col < N; Col++)
{
//Q toevoegen
bord[Row, Col] = true;
//Q + Q volgende Row controleren
if (bordValidatie(Row, Col, bord, N) && berekenQueens(Row + 1, N, bord))
{
return true;
}
//Q verwijderen indien niet door controle
bord[Row, Col] = false;
}
return false;
}
private static bool bordValidatie(int currentRow, int currentCol, bool[,] currentBord, int N)
{
int colstep = 1;
for (int i = currentRow - 1; i >= 0; i--)
{
//rechte lijn
if (currentBord[i, currentCol])
return false;
//linker diagonaal
if (currentCol - colstep >= 0)
{
if (currentBord[i, currentCol - colstep])
return false;
}
//rechter diagonaal
if (currentCol + colstep < N)
{
if (currentBord[i, currentCol + colstep])
return false;
}
colstep += 1;
}
return true;
}
}
}
MainWindow.xaml.cs
namespace NQueens
{
public partial class MainWindow : Window
{
public int iN { get { return Convert.ToInt32(txtN.Text); } set { txtN.Text = "" + value; } }
private bool[,] spelbord;
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
spelbord = new bool[iN, iN];
NQueen.berekenQueens(0, iN, spelbord);
visualise(iN, spelbord);
}
private void visualise(int N, bool[,] bord)
{
gridTekenen();
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
{
Rectangle rect = new Rectangle();
rect.Stretch = Stretch.Fill;
TextBlock txtB = new TextBlock();
if (spelbord[row, col])
{
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Colors.LightGreen;
rect.Fill = mySolidColorBrush;
txtB.Text = "Q";
}
rect.SetValue(Grid.ColumnProperty, col);
rect.SetValue(Grid.RowProperty, row);
txtB.SetValue(Grid.ColumnProperty, col);
txtB.SetValue(Grid.RowProperty, row);
gridPaneel.Children.Add(rect);
gridPaneel.Children.Add(txtB);
}
}
}
private void gridTekenen()
{
gridPaneel.ShowGridLines = true;
int grooteGrid = int.Parse(txtN.Text);
RowDefinition rowDef;
ColumnDefinition colDef;
for (int i = 0; i < grooteGrid; i++)
{
rowDef = new RowDefinition();
GridLengthConverter myGridLengthConverter = new GridLengthConverter();
GridLength gl1 = (GridLength)myGridLengthConverter.ConvertFromString(150 + "*");
rowDef.Height = gl1;
colDef = new ColumnDefinition();
colDef.Width = gl1;
gridPaneel.RowDefinitions.Add(rowDef);
gridPaneel.ColumnDefinitions.Add(colDef);
}
}
}
}
Code in WPF application when clicked on the menuItem.
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
// Create an assembly object to load our classes
string path = System.Environment.CurrentDirectory + "\\NQueens.dll";
Assembly ass = Assembly.LoadFile(path);
Console.WriteLine(path);
Type objType = ass.GetType("NQueens.NQueen");
// Create an instace of NQueens.NQueen
var instance = Activator.CreateInstance(objType);
// public static bool berekenQueens(int Row, int N, bool[,] bord)
var result = objType.InvokeMember("berekenQueens",BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
null, instance, new object[] { 1, /* Row */ 1, /* N */ new bool[,] { {true,false} } /* bord */
});
// private static bool bordValidatie(int currentRow, int currentCol, bool[,] currentBord, int N)
var result2 = objType.InvokeMember("bordValidatie", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic,
null, instance, new object[] { 1, /* Row */ 1, /* N */ new bool[,] { {true,false} } /* bord */, 1
});
}
I do not know what to do now. How can I show the NQueen program in my current Window when clicked on the menuItem.
NQueen class should be any kind of wpf control descendant. If it's a simple class, it cannot communicate with its container.
So you should instanciate NQueens.MainWindow instead of NQueens.NQueen and call the Show method.

Categories