my little program works very well, reading an xml file with 3 config values, reading a json-http-page and so on.
now there is a little thing i want to do: display the values out of the xml in my settings dialogue. i got this (Program.cs):
using ...
//*****************************************************************************
namespace t2bl
{
abstract class TANSS2BL
{
public static NotifyIcon notico;
//==========================================================================
public static void Main(string[] astrArg)
{
ContextMenu cm;
MenuItem miCurr;
cm = new ContextMenu();
miCurr = new MenuItem();
miCurr.Index = 0;
miCurr.Text = "&Settings";
miCurr.Click += new System.EventHandler(SettingsClick);
cm.MenuItems.Add(miCurr);
miCurr = new MenuItem();
miCurr.Index = 1;
miCurr.Text = "Beenden";
miCurr.Click += new System.EventHandler(ExitClick);
cm.MenuItems.Add(miCurr);
notico = new NotifyIcon();
notico.Icon = new Icon("tanss.ico");
notico.Text = "TANSS Busylight Connector";
notico.Visible = true;
notico.ContextMenu = cm;
notico.DoubleClick += new EventHandler(NotifyIconDoubleClick);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
Application.Run();
}
public static void bw_DoWork(object sender, DoWorkEventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("C://bll.config.xml");
XmlNode xmlurl = doc.SelectSingleNode("/settings/url");
string url = xmlurl.FirstChild.Value;
XmlNode xmluid = doc.SelectSingleNode("/settings/userID");
string userid_string = xmluid.FirstChild.Value;
XmlNode xmlrefresh = doc.SelectSingleNode("/settings/refresh");
string refresh_string = xmlrefresh.FirstChild.Value;
int userid = Convert.ToInt32(userid_string);
int refresh = 1000 * (Convert.ToInt32(refresh_string));
var controller = new BusylightUcController();
while (true)
{
WebClient client = new WebClient();
var downloadString = client.DownloadString(url + "/module/busylight.php? user=" + userid);
JObject colors = JObject.Parse(downloadString);
//Console.WriteLine(colors["color"]); //Debug
var colorStatus = Convert.ToInt32(colors["color"]);
switch (colorStatus)
{
check the colors and set the light
}
Thread.Sleep(refresh);
GC.Collect();
}
}
//==========================================================================
protected static void ExitClick(Object sender, EventArgs e)
{
notico.Dispose();
Application.Exit();
}
//==========================================================================
protected static void SettingsClick(Object sender, EventArgs e)
{
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
// This should open the "Settings"-Popup, containing 3 textboxes and a button to save them to xml.
SettingsDiag form1 = new SettingsDiag();
form1.Show();
}
//==========================================================================
protected static void NotifyIconDoubleClick(Object sender, EventArgs e)
{
// ...
}
}
}
and on the other side this (Form1.Designer.cs):
namespace Settingsdialog
{
partial class SettingsDiag
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(50, 28);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(163, 13);
this.label1.TabIndex = 0;
this.label1.Text = "TANSS Busylight connector v1.0";
this.label1.Click += new System.EventHandler(this.label1_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(53, 65);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(159, 20);
this.textBox1.TabIndex = 1;
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(271, 117);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "TANSS Busylight connector";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
}
}
How do i pass the values "url", "userid_string", "refresh_string" from the backgroundworker void to the "textbox1.Text=" Output?
Thanks!
There are many ways to accomplish that, one you had in other answers, I can suggest another one:
Because your worker is set to run async, you can for example, report the update progress using the worker event and then in the handler update the textbox
bw.WorkerReportsProgress = true;
bw.ProgressChanged += (o, args) => { textBox1.Text = args.UserState.ToString();}
It's clear that in your bw.DoWorkevent handler you need to report the progress operation passing the UserState as the string value you want to report and update, so inside the event handler you need to call
bw.ReportProgress(0, "you value to report");
hope this helps
If you want to communicate to your form the result of the background worker you could define your form as a member of TANSS2BL (and init it in Main).
Then in bw_DoWork you can call a method on your form with the information you want to display as parameters.
As bw_DoWork is on another thread don't forget to test InvokeRequired and BeginInvoke in your form before setting your textBox value.
Related
I have a Windows Forms App that is functioning in a way that I do not understand. I have created a simple app to reproduce the functionality to minimum logic for clarity. It has two forms.
Form1:
There is a button1 that when clicked adds rows to a datatable.
There is a button2 that displays a form and sends the datatable to the form.
Form2:
Form2 creates a dataview from the datatable and binds the dataview to a listbox. Form2 also has a button1 that does a this.Close() on the form. I read that anything opened with formName.Show() will be disposed of during .Close.
Here is where things are get weird. Form1 button1 can be clicked over and over each time clearing out the datatable and adds the rows again. Once from1 button2 is clicked and the form2 is displayed and then closed, going back to form1 and clicking button1 raises an error. The error is from the form2 (which has been closed) listBox1_SelectedIndexChanged event.
The question is, why is an event firing for a control that is gone on a form that is gone?
I have found several ways to avoid this but I am wanting to understand why it is happening such as setting the listbox datasource = null but would like to know what is going on.. Spent half a day trying to figure this out. SO community, please educate me here.
Form1 code
public partial class Form1 : Form
{
Boolean bInitialLoad = true;
DataTable dtHardware = new DataTable("Hardware");
Form2 multiServerView = new Form2();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
dtHardware.Clear();
if (bInitialLoad == true)
{
dtHardware.Columns.Add("ServerName", typeof(String));
dtHardware.Columns.Add("Environment", typeof(String));
}
DataRow drNewRow = dtHardware.NewRow();
drNewRow["ServerName"] = "SomeName";
drNewRow["Environment"] = "SomeEnvironment";
dtHardware.Rows.Add(drNewRow);
drNewRow = dtHardware.NewRow();
drNewRow["ServerName"] = "SomeName2";
drNewRow["Environment"] = "SomeEnvironment2";
dtHardware.Rows.Add(drNewRow);
bInitialLoad = false;
}
private void button2_Click(object sender, EventArgs e)
{
OpenMultiServerView();
}
private void OpenMultiServerView()
{
multiServerView = new Form2(dtHardware);
this.AddOwnedForm(multiServerView);
multiServerView.Show();
}
}
Form1 Designer
namespace WindowsFormsApp4
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(308, 390);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(107, 34);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(437, 296);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(102, 33);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(679, 482);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
}
}
Form2 code
public partial class Form2 : Form
{
DataView dvServers = null;
public Form2()
{
InitializeComponent();
}
public Form2(DataTable dt1)
{
InitializeComponent();
dvServers = new DataView(dt1);
}
private void Form2_Load(object sender, EventArgs e)
{
listBox1.DisplayMember = "ServerName";
listBox1.DataSource = dvServers;
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
System.Windows.Forms.FormCollection fc = Application.OpenForms;
foreach (System.Windows.Forms.Form frm in fc)
{
if (frm.Name == "Form2")
{
return;
}
}
MessageBox.Show("I am the listbox event from Form2");
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
}
Form2 Designer
namespace WindowsFormsApp4
{
partial class Form2
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.listBox1 = new System.Windows.Forms.ListBox();
this.button1 = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(23, 113);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(749, 287);
this.dataGridView1.TabIndex = 0;
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(291, 31);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(171, 69);
this.listBox1.TabIndex = 1;
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
//
// button1
//
this.button1.Location = new System.Drawing.Point(653, 415);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(118, 25);
this.button1.TabIndex = 2;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form2
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button1);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.dataGridView1);
this.Name = "Form2";
this.Text = "Form2";
this.Load += new System.EventHandler(this.Form2_Load);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.Button button1;
}
}
It's because the instance of Form2 isn't actually gone. You are correct in assuming that it has been disposed, since you called Show, but it has not been collected by the garbage collector. In fact, it can't be collected because in the code example provided Form1 has two references to the instance of Form2 that it created.
The first is in Form1.OwnedForms. The second is the field Form1.multiServerView.
You said you had a few ways to fix it, such as breaking the binding when Form2 closes, but I thought I'd just throw out this suggestion. If you don't actually need to create a new instance of Form2 every time you show it, you could just create one instance of it in the constructor of Form1, handle Form2.Closing and just hide Form2 when the user closes it.
So, something like...
public partial class Form1 : Form
{
//Removed bInitialLoad, we'll set up the data table in the constructor.
DataTable dtHardware = new DataTable("Hardware");
Form2 multiServerView; //No longer initalizing here, we'll do that in the constructor.
public Form1()
{
InitializeComponent();
dtHardware.Columns.Add("ServerName", typeof(String));
dtHardware.Columns.Add("Environment", typeof(String));
multiServerView = new Form2(dtHardware);
AddOwnedForm(multiServerView);
}
private void button1_Click(object sender, EventArgs e)
{
dtHardware.Clear();
//Removed the check of bInitialLoad.
DataRow drNewRow = dtHardware.NewRow();
drNewRow["ServerName"] = "SomeName";
drNewRow["Environment"] = "SomeEnvironment";
dtHardware.Rows.Add(drNewRow);
drNewRow = dtHardware.NewRow();
drNewRow["ServerName"] = "SomeName2";
drNewRow["Environment"] = "SomeEnvironment2";
dtHardware.Rows.Add(drNewRow);
//Removed setting bInitialLoad.
}
private void button2_Click(object sender, EventArgs e)
{
OpenMultiServerView();
}
private void OpenMultiServerView()
{
multiServerView.Show(); //Just show it.
}
}
public partial class Form2 : Form
{
DataView dvServers = null;
//Removed the empty constructor since Form1 no longer needs it.
public Form2(DataTable dt1)
{
InitializeComponent();
dvServers = new DataView(dt1);
}
private void Form2_Load(object sender, EventArgs e)
{
listBox1.DisplayMember = "ServerName";
listBox1.DataSource = dvServers;
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("I am the listbox event from Form2");
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form2_Closing(object sender, FormClosingEventArgs e)
{
//Don't forget to wire it up in the designer!
//If the user clicks "button1" or the "X" then just hide the form.
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Hide();
}
}
}
This way, there is only ever one instance of Form2 for Form1. You don't have to worry about instances of Form2 that are disposed but not collected yet triggering events when something on Form1 alters the data source.
I am trying to change one cell inside a DataGridViewComboBoxColumn from
DataGridViewComboBoxCell into a DataGridViewTextBoxCell
here is the line i am typing in order to change it:
dataGridView1[0,3] = new DataGridViewTextBoxCell();
after running this line the cell remains in its DataGridViewComboBoxCell type.
Thanks in advance,
Nadav
I cannot distinguish any problems. The following form creates a DataGridView and provides a DataGridViewComboBoxColumn with three items asdf qwer and yxcv as possible combinations. During the Load event of the Form the grid is filled with four valid rows. Afterwards your line of code is performed, which performs as expected.
Am i missing something?
Here is the code:
public partial class Form1 : Form
{
public Form1() { InitializeComponent(); }
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Rows.Add("asdf");
dataGridView1.Rows.Add("qwer");
dataGridView1.Rows.Add("yxcv");
dataGridView1.Rows.Add("asdf");
dataGridView1[0, 3] = new DataGridViewTextBoxCell();
}
}
Designer File's code:
partial class Form1
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.Column1 = new System.Windows.Forms.DataGridViewComboBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1});
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView1.Location = new System.Drawing.Point(0, 0);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(470, 262);
this.dataGridView1.TabIndex = 0;
//
// Column1
//
this.Column1.HeaderText = "Column1";
this.Column1.Items.AddRange(new object[] {
"asdf",
"qwer",
"yxcv"});
this.Column1.Name = "Column1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(470, 262);
this.Controls.Add(this.dataGridView1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.DataGridViewComboBoxColumn Column1;
}
I'm trying to implement a custom messagebox (Ok,Cancel) using .NET Compact Framework 3.5 on Form Application. How I implement it?
If you are after a messagebox with ok and cancel buttons you can use
MessageBox.Show(this, "Message", "caption", MessageBoxButtons.OKCancel);
If you want a custom look/feel and any buttons that you don't normally see on messageboxes, then you have to make your own form to display
MessageBoxButton options
A co-worker and I came up with the following class to act as a sort of dynamic message box.
Here's the designer code:
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblMessage = new System.Windows.Forms.Label();
this.btnRight = new System.Windows.Forms.Button();
this.btnLeft = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// lblMessage
//
this.lblMessage.AutoSize = true;
this.lblMessage.Location = new System.Drawing.Point(12, 39);
this.lblMessage.Name = "lblMessage";
this.lblMessage.Size = new System.Drawing.Size(35, 13);
this.lblMessage.TabIndex = 0;
this.lblMessage.Text = "label1";
//
// btnRight
//
this.btnRight.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.btnRight.Location = new System.Drawing.Point(89, 73);
this.btnRight.Name = "btnRight";
this.btnRight.Size = new System.Drawing.Size(75, 23);
this.btnRight.TabIndex = 1;
this.btnRight.UseVisualStyleBackColor = true;
//
// btnLeft
//
this.btnLeft.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.btnLeft.Location = new System.Drawing.Point(8, 73);
this.btnLeft.Name = "btnLeft";
this.btnLeft.Size = new System.Drawing.Size(75, 23);
this.btnLeft.TabIndex = 0;
this.btnLeft.UseVisualStyleBackColor = true;
//
// CustomMessageBox
//
this.AcceptButton = this.btnLeft;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ClientSize = new System.Drawing.Size(170, 114);
this.ControlBox = false;
this.Controls.Add(this.btnLeft);
this.Controls.Add(this.btnRight);
this.Controls.Add(this.lblMessage);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.KeyPreview = true;
this.MinimumSize = new System.Drawing.Size(176, 120);
this.Name = "CustomMessageBox";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "CustomMessageBox";
this.Load += new System.EventHandler(this.frmCustomMessageBoxLoad);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblMessage;
private System.Windows.Forms.Button btnRight;
private System.Windows.Forms.Button btnLeft;
And here's the code behind the form:
internal partial class CustomMessageBox : Form
{
#region Fields
public readonly MessageBoxButtons _buttons;
#endregion
//need to seal properties to override from derived class
#region Constructors
/// <summary>
/// This constructor is required for designer support.
/// </summary>
public CustomMessageBox()
{
InitializeComponent();
}
public CustomMessageBox(string message, string title, MessageBoxButtons buttons)
{
InitializeComponent();
Text = title;
lblMessage.Text = message;
_buttons = buttons;
}
#endregion
#region Properties
public override sealed string Text
{
get { return base.Text; }
set { base.Text = value; }
}
#endregion
#region private
private void frmCustomMessageBoxLoad(object sender, EventArgs e)
{
lblMessage.Left = (ClientSize.Width - lblMessage.Width) / 2;
switch(_buttons)
{
case MessageBoxButtons.OKCancel:
{
btnLeft.Text = #"OK";
btnLeft.DialogResult = DialogResult.OK;
btnRight.Text = #"Cancel";
btnRight.DialogResult = DialogResult.Cancel;
AcceptButton = btnLeft;
break;
}
case MessageBoxButtons.OK:
{
btnLeft.Text = #"OK";
btnLeft.DialogResult = DialogResult.OK;
btnRight.Hide();
btnLeft.Left = (ClientSize.Width - btnLeft.Width) / 2;
AcceptButton = btnLeft;
break;
}
case MessageBoxButtons.YesNo:
{
btnLeft.Text = #"Yes";
btnLeft.DialogResult = DialogResult.Yes;
btnRight.Text = #"No";
btnRight.DialogResult = DialogResult.No;
AcceptButton = btnLeft;
break;
}
default :
{
btnLeft.Hide();
btnRight.Hide();
break;
}
}
AcceptButton = btnLeft;
}
#endregion
}
You'll need to implement your own custom Form and access it with
myForm.ShowDialog();
Here's a guide to DialogBoxes and you can follow this guide this guide to create your own dialog box.
But if you're only using OK/Cancel buttons, what's wrong with MessageBox?
I creating diagnostic application for PLCs. I have one form and a few Controls, which was inherited of UserControl. This Controls I switch. One view is Dashboard, Graph, and so on. When the graph is running, exception is occured. Exception is showed on line "base.Dispose(disposing)" in Form1.Designer.cs. Do you have any idea, how I can fix it? Thanks for any ideas.
This is code of Form1.Designer.cs. Error is show on line base.Dispose(disposing). Basicaly I don't know what this part of code do. That I can't repair it. Can somebody tell me, how it works? When is this part called? I don't find any use of method Dispose() in my program, only override methodes in each Control (inherited from UserControl). Thanks
namespace WindowsFormsApplication1
{
partial class Form1
{
///
/// Required designer variable.
///
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
/*Updated 8.4.2013*/
//try
//{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
//}
//catch { }
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
this.btn_ChangeLanguage = new System.Windows.Forms.Button();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.Zobraz_Palubka = new System.Windows.Forms.Button();
this.Zobraz_Verzi = new System.Windows.Forms.Button();
this.Zobraz_error = new System.Windows.Forms.Button();
this.Zobraz_Nastaveni = new System.Windows.Forms.Button();
this.Zobraz_TestIO = new System.Windows.Forms.Button();
this.Zobraz_monitor = new System.Windows.Forms.Button();
this.statusStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel1});
resources.ApplyResources(this.statusStrip1, "statusStrip1");
this.statusStrip1.Name = "statusStrip1";
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
resources.ApplyResources(this.toolStripStatusLabel1, "toolStripStatusLabel1");
//
// btn_ChangeLanguage
//
this.btn_ChangeLanguage.Image = global::WindowsFormsApplication1.Properties.Resources.flag_cze_mini;
resources.ApplyResources(this.btn_ChangeLanguage, "btn_ChangeLanguage");
this.btn_ChangeLanguage.Name = "btn_ChangeLanguage";
this.btn_ChangeLanguage.UseVisualStyleBackColor = true;
this.btn_ChangeLanguage.Click += new System.EventHandler(this.btn_ChangeLanguage_Click);
this.btn_ChangeLanguage.MouseEnter += new System.EventHandler(this.Zobraz_Nastaveni_MouseEnter);
this.btn_ChangeLanguage.MouseLeave += new System.EventHandler(this.Zobraz_Nastaveni_MouseLeave);
//
// pictureBox1
//
this.pictureBox1.BackColor = System.Drawing.Color.Transparent;
this.pictureBox1.Image = global::WindowsFormsApplication1.Properties.Resources.trojuhelnik;
resources.ApplyResources(this.pictureBox1, "pictureBox1");
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.TabStop = false;
//
// Zobraz_Palubka
//
this.Zobraz_Palubka.Image = global::WindowsFormsApplication1.Properties.Resources.tachometr_mini;
resources.ApplyResources(this.Zobraz_Palubka, "Zobraz_Palubka");
this.Zobraz_Palubka.Name = "Zobraz_Palubka";
this.Zobraz_Palubka.UseVisualStyleBackColor = true;
this.Zobraz_Palubka.Click += new System.EventHandler(this.Zobraz_Click);
this.Zobraz_Palubka.MouseEnter += new System.EventHandler(this.Zobraz_Nastaveni_MouseEnter);
this.Zobraz_Palubka.MouseLeave += new System.EventHandler(this.Zobraz_Nastaveni_MouseLeave);
//
// Zobraz_Verzi
//
this.Zobraz_Verzi.Image = global::WindowsFormsApplication1.Properties.Resources.info_mini;
resources.ApplyResources(this.Zobraz_Verzi, "Zobraz_Verzi");
this.Zobraz_Verzi.Name = "Zobraz_Verzi";
this.Zobraz_Verzi.UseVisualStyleBackColor = true;
this.Zobraz_Verzi.Click += new System.EventHandler(this.Zobraz_Click);
this.Zobraz_Verzi.MouseEnter += new System.EventHandler(this.Zobraz_Nastaveni_MouseEnter);
this.Zobraz_Verzi.MouseLeave += new System.EventHandler(this.Zobraz_Nastaveni_MouseLeave);
//
// Zobraz_error
//
this.Zobraz_error.Image = global::WindowsFormsApplication1.Properties.Resources.error1_mini;
resources.ApplyResources(this.Zobraz_error, "Zobraz_error");
this.Zobraz_error.Name = "Zobraz_error";
this.Zobraz_error.UseVisualStyleBackColor = true;
this.Zobraz_error.Click += new System.EventHandler(this.Zobraz_Click);
this.Zobraz_error.MouseEnter += new System.EventHandler(this.Zobraz_Nastaveni_MouseEnter);
this.Zobraz_error.MouseLeave += new System.EventHandler(this.Zobraz_Nastaveni_MouseLeave);
//
// Zobraz_Nastaveni
//
this.Zobraz_Nastaveni.Image = global::WindowsFormsApplication1.Properties.Resources.settings_mini;
resources.ApplyResources(this.Zobraz_Nastaveni, "Zobraz_Nastaveni");
this.Zobraz_Nastaveni.Name = "Zobraz_Nastaveni";
this.Zobraz_Nastaveni.UseVisualStyleBackColor = true;
this.Zobraz_Nastaveni.Click += new System.EventHandler(this.Zobraz_Click);
this.Zobraz_Nastaveni.MouseEnter += new System.EventHandler(this.Zobraz_Nastaveni_MouseEnter);
this.Zobraz_Nastaveni.MouseLeave += new System.EventHandler(this.Zobraz_Nastaveni_MouseLeave);
//
// Zobraz_TestIO
//
this.Zobraz_TestIO.Image = global::WindowsFormsApplication1.Properties.Resources.testIO_mini;
resources.ApplyResources(this.Zobraz_TestIO, "Zobraz_TestIO");
this.Zobraz_TestIO.Name = "Zobraz_TestIO";
this.Zobraz_TestIO.UseVisualStyleBackColor = true;
this.Zobraz_TestIO.Click += new System.EventHandler(this.Zobraz_Click);
this.Zobraz_TestIO.MouseEnter += new System.EventHandler(this.Zobraz_Nastaveni_MouseEnter);
this.Zobraz_TestIO.MouseLeave += new System.EventHandler(this.Zobraz_Nastaveni_MouseLeave);
//
// Zobraz_monitor
//
this.Zobraz_monitor.Image = global::WindowsFormsApplication1.Properties.Resources.line_graph_icon_mini;
resources.ApplyResources(this.Zobraz_monitor, "Zobraz_monitor");
this.Zobraz_monitor.Name = "Zobraz_monitor";
this.Zobraz_monitor.UseVisualStyleBackColor = true;
this.Zobraz_monitor.Click += new System.EventHandler(this.Zobraz_Click);
this.Zobraz_monitor.MouseEnter += new System.EventHandler(this.Zobraz_Nastaveni_MouseEnter);
this.Zobraz_monitor.MouseLeave += new System.EventHandler(this.Zobraz_Nastaveni_MouseLeave);
//
// Form1
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.btn_ChangeLanguage);
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.Zobraz_Palubka);
this.Controls.Add(this.Zobraz_Verzi);
this.Controls.Add(this.Zobraz_error);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.Zobraz_Nastaveni);
this.Controls.Add(this.Zobraz_TestIO);
this.Controls.Add(this.Zobraz_monitor);
this.Name = "Form1";
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button Zobraz_monitor;
private System.Windows.Forms.Button Zobraz_Nastaveni;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
private System.Windows.Forms.Button Zobraz_TestIO;
private System.Windows.Forms.Button Zobraz_error;
private System.Windows.Forms.Button Zobraz_Verzi;
private System.Windows.Forms.Button Zobraz_Palubka;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Button btn_ChangeLanguage;
}
}
Here is exception detail:
System.InvalidOperationException was unhandled by user code
Message=Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Form.UpdateMenuHandles(MainMenu menu, Boolean forceRedraw)
at System.Windows.Forms.Form.UpdateMenuHandles()
at System.Windows.Forms.Form.MenuChanged(Int32 change, Menu menu)
at System.Windows.Forms.Form.Dispose(Boolean disposing)
at WindowsFormsApplication1.Form1.Dispose(Boolean disposing) in c:__Projects__\C#\RailJay Diagnostic SW\20130408\Motor\Motor\Form1.Designer.cs:line 23
at System.ComponentModel.Component.Dispose()
at System.Windows.Forms.ApplicationContext.Dispose(Boolean disposing)
at System.Windows.Forms.Application.ThreadContext.DisposeThreadWindows()
InnerException:
It appears that you're calling Dispose from a thread other than the GUI thread. You can't do that.
You need to be more specific - perhaps adding some code to what you are trying to do, where?
[EDIT]
As Jim mentioned, you are referencing a form from a seperate thread;
Here is exception detail:
System.InvalidOperationException was unhandled by user code
Message=Cross-thread operation not valid: Control 'Form1' accessed
from a thread other than the thread it was created on
This means that you are trying to dispose Form1 from a thread that it was not created on.
Have you got sperate threads running in the application, if so, this is the first place to look.
Are you closing the Form1 anywhere within code?
I have been unable to figure out how to keep a context menu open after handling a click event past the first level. Here is an example of where I have a context menu with a menu of checkable menus. I open up the context menu after handling the click event, but I have to manually return to the inner menu. Is there a way to open up the outer menu programmatically or to prevent the inner menu from closing?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NoCloseContextMenu
{
public partial class Form1 : Form
{
bool[] store_checks = new bool[8];
public Form1()
{
InitializeComponent();
richTextBox1.AppendText("http://");
richTextBox1.LinkClicked += new LinkClickedEventHandler(richTextBox1_LinkClicked);
}
void richTextBox1_LinkClicked(object sender, LinkClickedEventArgs e)
{
MenuItemExtended[] inner_menuitems = new MenuItemExtended[8];
for (int i = 0; i < store_checks.Length; i++)
{
MenuItemExtended inner_menuitem = new MenuItemExtended("Check #" + i.ToString());
inner_menuitem.menuitem_index = i;
inner_menuitem.contextmenu_point = this.PointToClient(Cursor.Position);
inner_menuitem.Checked = store_checks[i];
inner_menuitem.Shortcut = (Shortcut)(131120 + i); //Ctrl+i = 131120+i
inner_menuitem.ShowShortcut = true;
inner_menuitem.Click += new EventHandler(inner_menuitem_Click);
inner_menuitems[i] = inner_menuitem;
}
MenuItem outer_menu = new MenuItem("Outer Menu", inner_menuitems);
ContextMenu context_menu = new ContextMenu(new MenuItem[] { outer_menu });
context_menu.Show(this, this.PointToClient(Cursor.Position));
}
void inner_menuitem_Click(object sender, EventArgs e)
{
MenuItemExtended sender_menu = (MenuItemExtended)sender;
store_checks[sender_menu.menuitem_index] = !store_checks[sender_menu.menuitem_index];
sender_menu.Checked = !sender_menu.Checked;
sender_menu.GetContextMenu().Show(this, sender_menu.contextmenu_point);
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// richTextBox1
//
this.richTextBox1.Location = new System.Drawing.Point(13, 13);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(100, 96);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.richTextBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.RichTextBox richTextBox1;
}
public class MenuItemExtended : MenuItem
{
public int menuitem_index;
public Point contextmenu_point;
public MenuItemExtended(string text)
{
this.Text = text;
}
}
}
Also, is there any way to get the "Control + number" shortcuts to work and activate the click event? Thanks in advance for the help!
I did not find any way to prevent the context menu from closing so instead I used ContextMenuStrip and ToolStripMenuItem. This also fixed the problem I had with shortcuts not working before. I handle the Closing event of the menu containing the checkable items and cancel closing if the items were clicked/checked.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NoCloseContextMenu
{
public partial class Form1 : Form
{
bool[] store_checks = new bool[8];
public Form1()
{
InitializeComponent();
richTextBox1.AppendText("http://");
richTextBox1.LinkClicked += new LinkClickedEventHandler(richTextBox1_LinkClicked);
}
void richTextBox1_LinkClicked(object sender, LinkClickedEventArgs e)
{
ToolStripMenuItem[] inner_menuitems = new ToolStripMenuItem[8];
for (int i = 0; i < store_checks.Length; i++)
{
ToolStripMenuItem inner_menuitem = new ToolStripMenuItem("Check #" + i.ToString());
inner_menuitem.Checked = store_checks[i];
inner_menuitem.CheckOnClick = true;
inner_menuitem.ShortcutKeys = Keys.Control | (Keys)(48 + i); //Di = 48 + i
inner_menuitem.ShowShortcutKeys = true;
inner_menuitem.Click += new EventHandler(inner_menuitem_Click);
inner_menuitem.Tag = i.ToString();
inner_menuitems[i] = inner_menuitem;
}
ToolStripMenuItem outer_menu = new ToolStripMenuItem("Outer Menu", null, inner_menuitems);
outer_menu.DropDown.Closing += new ToolStripDropDownClosingEventHandler(DropDown_Closing);
ContextMenuStrip context_menu = new ContextMenuStrip();
context_menu.Items.Add(outer_menu);
context_menu.Show(this, this.PointToClient(Cursor.Position));
}
void DropDown_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
{
e.Cancel = true;
((ToolStripDropDownMenu)sender).Invalidate();
}
}
void inner_menuitem_Click(object sender, EventArgs e)
{
ToolStripMenuItem sender_menu = (ToolStripMenuItem)sender;
int index = int.Parse(sender_menu.Tag.ToString());
store_checks[index] = !store_checks[index];
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// richTextBox1
//
this.richTextBox1.Location = new System.Drawing.Point(13, 13);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(100, 96);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.richTextBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.RichTextBox richTextBox1;
}
}
You can also select certain buttons from within your unclosable submenu to cause the context menu to close normally. For a specific ToolStripMenuItem to close the menu normally, give it a different event method to call:
inner_menuitem.Click += new EventHandler(inner_menuitem_Can_Close);
And use the following code in the method (works regardless of how deep the menus go):
void inner_menuitem_Can_Close(object sender, EventArgs e)
{
ToolStripMenuItem castSender = (ToolStripMenuItem)sender;
object owner = castSender.OwnerItem;
while (owner is ToolStripMenuItem)
{
if (((ToolStripMenuItem)owner).Owner is ContextMenuStrip)
((ContextMenuStrip)((ToolStripMenuItem)owner).Owner).Close();
owner = ((ToolStripMenuItem)owner).OwnerItem;
}
}
I would advise strongly against handling click events on 'parent' context menu items - let the OS handle this for you.