ListView problems, Cross class operation - c#

I'm trying to add an ListViewItem to a listView on the main form (Form1), from another class(Comm).
Form1:
public ListViewItem lvi_tmp;
private void Form1_Load(object sender, EventArgs e)
{
comm = new Comm(this);
}
public void add_to_reg(ListViewItem tmp)
{
lvi_tmp = tmp;
this.Invoke(new EventHandler(add_to_reg_event));
}
public void add_to_reg_event(Object sender, EventArgs e)
{
lst_reg.Items.Add(lvi_tmp);
lst_reg.Refresh();
this.Refresh();
}
Comm:
public Form1 mainFrm { get; set; }
public Comm (Form1 _form1)
{
mainFrm = _form1;
}
private void Add_item()
{
lvi = new ListViewItem("itemTest");
lvi.SubItems.Add("subitemTest");
lvi.Tag = 1;
mainFrm.add_to_reg(lvi);
}
This code throwing the next Exception:
"Invoke or BeginInvoke cannot be called on a control until the window handle has been created."
Any ideas?

You can check InvokeRequired before callling BeginInvoke(). Perhaps this will work for you:
public void add_to_reg(ListViewItem tmp)
{
lvi_tmp = tmp;
if (this.InvokeRequired))
this.Invoke(new EventHandler(add_to_reg_event));
else
add_to_reg_event(null, null);
}
Although I'd split up add_to_reg_event() and use a lambda to avoid that temporary variable:
public void add_to_reg(ListViewItem tmp)
{
if (this.InvokeRequired))
this.Invoke(new Action(() => add_to_reg_impl(tmp)));
else
add_to_reg_impl(tmp);
}
private void add_to_reg_impl(ListViewItem item)
{
lst_reg.Items.Add(item);
lst_reg.Refresh();
this.Refresh();
}

Related

Manipulating similar objects in a form using another form

I am new to C# and I want to utilize the forms with one another.
I have 2 forms. (1)MMCMLibrary_home and (2)MMCMLibrary_reserve.
In this project, I'm in the stage of changing the label background colors in Form 1 but can't seem to utilize Form 2 to process it.
These are my necessary codes so far:
FORM 1
namespace MMCM_Library
{
public partial class MMCMLibrary_home : Form
{
public static MMCMLibrary_home instance;
//DCR1 Labels
public Label lbl1_1;
public Label lbl1_2;
public Label lbl1_3;
public Label lbl1_4;
public MMCMLibrary_home()
{
InitializeComponent();
instance = this;
lbl1_1 = lblDCR1_9;
lbl1_2 = lblDCR2_11;
lbl1_3 = lblDCR1_1;
lbl1_4 = lblDCR1_3;
public void btnDCR1_Click(object sender, EventArgs e)
{
var reserveDCR1 = new MMCMLibrary_reserve();
reserveDCR1.Show();
}
public void btnDCR2_Click(object sender, EventArgs e)
{
var reserveDCR2 = new MMCMLibrary_reserve();
reserveDCR2.Show();
}
public void btnDCR3_Click(object sender, EventArgs e)
{
var reserveDCR3 = new MMCMLibrary_reserve();
reserveDCR3.Show();
}
public void btnDCR4_Click(object sender, EventArgs e)
{
var reserveDCR4 = new MMCMLibrary_reserve();
reserveDCR4.Show();
}
}
}
FORM 2
when I click any reserve now button in form 1 it will open form 2. However, if I pick a radio button, the background change will always be applied to Discussion Room 1 even I reserved for discussion room 2
namespace MMCM_Library
{
public partial class MMCMLibrary_reserve : Form
{
public static MMCMLibrary_reserve instance;
public MMCMLibrary_reserve()
{
InitializeComponent();
instance = this;
}
private void MMCMLibrary_reserve_Load(object sender, EventArgs e)
{
}
private void splitContainer1_Panel2_Paint(object sender, PaintEventArgs e)
{
}
private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e)
{
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
}
private void radioButton1_CheckedChanged_1(object sender, EventArgs e)
{
}
private void btnDCR1_Click(object sender, EventArgs e)
{
}
public void btnDCRoomsReserve_Click(object sender, EventArgs e)
{
if (rbtn9.Checked)
{
MMCMLibrary_home.instance.lbl1_1.BackColor = System.Drawing.Color.Red;
}
}
}
}
Can you help me to device an efficient way to solve this. Can you also suggest a database method suitable for my beginner project.
You've said that:
the background change will always be applied to Discussion Room 1
Well, yes. It seems you don't pass specific object into Form2. There's strightforward:
MMCMLibrary_home.instance.lbl1_1.BackColor = System.Drawing.Color.Red;
So you'll be always changing backcolor of lbl1_1 of your Form1. What needs to be done is to indicate which room has been selected. You can assign room after you click the button by passing the int parameter:
public void btnDCR1_Click(object sender, EventArgs e)
{
var reserveDCR1 = new MMCMLibrary_reserve(1);
reserveDCR1.Show();
}
or:
public void btnDCR2_Click(object sender, EventArgs e)
{
var reserveDCR2 = new MMCMLibrary_reserve(2);
reserveDCR2.Show();
}
Then, in Form2, at the very top, add something like:
int room; to be able to assign the room number in Form2:
public MMCMLibrary_reserve(int roomNumber)
{
InitializeComponent();
room = roomNumber;
instance = this;
}
And then you could just select room you clicked, by:
public void btnDCRoomsReserve_Click(object sender, EventArgs e)
{
if (rbtn9.Checked)
{
if(room == 1)
{
MMCMLibrary_home.instance.lbl1_1.BackColor = System.Drawing.Color.Red;
}
else if(room == 2)
{
MMCMLibrary_home.instance.lbl1_2.BackColor = System.Drawing.Color.Red;
}
else if(room == 3)
{
MMCMLibrary_home.instance.lbl1_3.BackColor = System.Drawing.Color.Red;
}
else if(room == 4)
{
MMCMLibrary_home.instance.lbl1_4.BackColor = System.Drawing.Color.Red;
}
}
else if(radioButton2.Checked)
{
//etc.
}
else if(radioButton3.Checked)
{
//etc.
}
else if(radioButton4.Checked)
{
//etc.
}
}
I think that was the problem. Try it and let us know.

Second form is not showing properly

My main form is a mdi container with a menu strip. When I choose Options-Maintenance I want another mdi to appear. This kind of works. Instead of another mdi container along with the design, a regular smaller form appears and not sure why.
public partial class mdiMain : Form
{
static string sTo = ConfigurationManager.ConnectionStrings["connectionTo"].ToString();
public myDataAccess3 data;
public mdiMain()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
data = new myDataAccess3(sTo);
frmLogOn frmLogOn = new frmLogOn(data);
if (frmLogOn.ShowDialog().Equals(DialogResult.Cancel))
{
frmLogOn.Close();
frmLogOn = null;
Application.Exit();
return;
}
frmLogOn.Close();
frmLogOn = null;
this.Focus();
}
catch (Exception e1)
{
MessageBox.Show("There was an error " + e1);
}
}
private void maintenanceToolStripMenuItem_Click(object sender, EventArgs e)
{
mdiMaintenance maintenance = new mdiMaintenance(this,data);
maintenance.Enabled = true;
maintenance.Show();
}
}
public partial class mdiMaintenance : Form
{
private myDataAccess3 data;
private mdiMain mdiMain;
public mdiMaintenance()
{
InitializeComponent();
}
public mdiMaintenance(mdiMain mdiMain, myDataAccess3 data)
{
// TODO: Complete member initialization
this.mdiMain = mdiMain;
this.data = data;
}
private void mdiMaintenance_Load(object sender, EventArgs e)
{
}
Thanks for the help
If the form is intended to be an MDI Child then you need to set the MdiParent property:
private void maintenanceToolStripMenuItem_Click(object sender, EventArgs e)
{
mdiMaintenance maintenance = new mdiMaintenance(this,data);
maintenance.Enabled = true;
maintenance.MdiParent = this;
maintenance.Show();
}

Transmitting events from a Winform to another in C#

How can I click a Button(to generate a color) in one form and change text color in a RichTextBox in a another form? Thanks in advance. (Newbie trying to understand C#)
Some code:
1.WinForm
public delegate void ColorWindowEvent(Object sender, SecondrWindowEventArgs e);
public partial class ColorWindow : Form
{
public event ColorWindowEvent myEventHandler;
public ColorWindow ()
{
InitializeComponent();
}
public void MyEvent(Object sender, ColorWindowEventArgs e)
{
string s = "";
myEventHandler(this, new SecondWindowEventArgs(s));
}
private void btnRed_Click(object sender, EventArgs e)
{
Color c = Color.Red;
string s = c.ToString();
this.Close();
}
private void btnBlue_Click(object sender, EventArgs e)
{
Color c = Color.Blue;
string str = c.ToString();
this.Close();
}
private void btnGreen_Click(object sender, EventArgs e)
{
Color c = Color.Green;
string s = c.ToString();
this.Close();
}
}
public class SecondWindowEventArgs : EventArgs
{
private string s;
public SecondWindowEventArgs(string _s)
{
s = _s;
}
#region
public string S
{
get;
set;
}
#endregion
}
2.WinForm
public delegate void SecondWindowEvent(Object sender, FirstWindowEventArgs e);
public partial class SecondWindow : Form
{
public event SecondWindowEvent myEventHandler;
private string s;
public SecondWindow(String _s)
{
s = _s;
InitializeComponent();
}
public void MyEvent(Object sender, FirstWindowEventArgs e)
{
string str = rtf2.Text;
if (str != null)
{
myEventHandler(this, new FirstWindowEventArgs(str));
}
}
private void btnQuit_Click(object sender, EventArgs e)
{
this.Close();
}
private void rtf2_TextChanged(object sender, EventArgs e)
{
if (myEventHandler != null)
{
myEventHandler(this, new FirstWindowEventArgs(rtf2.Text.Substring(rtf2.Text.Length - 1)));
rtf2.ForeColor = Color.FromName(e.ToString());
}
}
private void btnClearText_Click(object sender, EventArgs e)
{
rtf2.Text = " ";
}
private void rtf2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Escape)
{
FargeVindu fargeVindu = new FargeVindu();
fargeVindu.minEventHandler += new FargeVinduEvent(fargeVindu_minEventHandler);
fargeVindu.Show();
}
else if (e.KeyData == Keys.Delete)
{
}
}
protected void ColorWindow_myEventHandler(object sender, SecondWindowEventArgs e)
{
rtf2.ForeColor = Color.FromName(s);
}
Random random = new Random();
private void SecondWindow_Load(object sender, EventArgs e)
{
lblText.ForeColor = Color.FromArgb(random.Next(255),
random.Next(255), random.Next(255));
}
public Color getColor
{
get;
set;
}
}
3.WinForm
public partial class FirstWindow : Form
{
public FirstWindow()
{
InitializeComponent();
}
private void btnQuit_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnClick_Click(object sender, EventArgs e)
{
string str = " ";
SecondWindow secondWindow = new SecondWindow (str);
secondWindow.myEventHandler += new SecondWindowEvent(secondWindow_myEventHandler);
secondWindow.Show();
}
protected void secondWindow_myEventHandler(object sender, FirstWindowEventArgs e)
{
rtf1.AppendText(String.Format(e.Tekst));
}
public void btnClearText_Click(object sender, EventArgs e)
{
rtf1.Text = " ";
}
}
Clarification from comments
I would like the Form to Change the color on close after the button is clicked. This is what I tried:
private void btnRed_Click(object sender, EventArgs e)
{
Color c = Color.Red;
string s = c.ToString();
this.Close();
}
To answer your question, create a property on your Color Form that is set by your button you can then read it after the Form is closed when it returns from your ShowDialog statement.
Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
if(frm2.ShowDialog() == DialogResult.OK)
{
//this.BackColor=frm2.getColor; helps if I read the question more closely
richTextBox1.SelectionColor = frm2.getColor;
}
}
}
Form2
public partial class Form2 : Form
{
public Color getColor { get; set; }
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
getColor = Color.Red;
DialogResult = DialogResult.OK;
}
}
After playing with the code that you posted and added some missing handlers, it looks like the text of your color is coming in the Format of Color [Red] ColorFromName has no idea how to parse that so you will need to get the actual color name by using String.Split Something like this.
protected void ColorWindow_myEventHandler(object sender, SecondWindowEventArgs e)
{
rtf2.ForeColor = Color.FromName(e.S.Split(new string[]{"[","]"},StringSplitOptions.None)[1]);
}
I also noticed that you are setting your rtf2.ForeColor everytime that your text changes, I removed it and am now able to change the ForeColor of the RichText box. I would be a lot easier/cleaner IMHO if you just passed the actual Color Object instead of changing it to a string and back.
This is the modified TextChanged Method note the commented out rtf2.ForeColor statement it does not belong there.
private void rtf2_TextChanged(object sender, EventArgs e)
{
if (myEventHandler != null)
{
myEventHandler(this, new FirstWindowEventArgs(rtf2.Text.Substring(rtf2.Text.Length -1)));
// rtf2.ForeColor = Color.FromName(e.ToString());
}
}

How can i associate Winform's Progress Bar changes with other function

I have a progress bar which codes in below. I find this code from net. i really want to do when i click one button this button do some process and i count it.how can i understand when is there any changes in ReadExistingExcel fucnc this. This function is in other class and there are a lot of loop in this function
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Class1 yeni = new Class1();
yeni.Update();
}
public void UpdateMyProgressBar(int i)
{
progressBar1.Value=i;
backgroundWorker1.ReportProgress(i);
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
this.Text = e.ProgressPercentage.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
}
other class
public class Class1
{
public void Update()
{
for (int i = 0; i < 100; i++)
{
Form1 ins = new Form1();
ins.UpdateMyProgressBar(i);
}
}
}
As your code stand now the Form1 class creates a new instance of Class1 which then, inside the Update method, creates 100 new instances of Form1. It's not getting a reference to the existing form. And that's your problem.
Try changing your Class1 code like this:
public class Class1
{
public Class1(Form1 form1)
{
_form1 = form1;
}
private Form1 _form1;
public void Update()
{
for (int i = 0; i < 100; i++)
{
_form1.UpdateMyProgressBar(i);
}
}
}
Then change Form1 like this:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Class1 yeni = new Class1(this);
yeni.Update();
}
public void UpdateMyProgressBar(int i)
{
backgroundWorker1.ReportProgress(i);
}
Well it sounds like you just need to have a public void to update the progressbar value.
public void UpdateProgressBar(int val)
{
progressBar1.Value = val;
}
This can then be called from your other classes by referring to your current class.
So if your current class is called Class1 and you want to call it from Class10 you would simply do
Class1.UpdateProgressBar(10);

Object does not create when using one as global variable

I have wrapper class over Thread:
public class ThreadWrapper
{
private bool Terminated = false;
private string threadName;
private Thread _thread;
public bool needToTerminate
{
get
{
lock (this)
{
return Terminated;
}
}
}
public string ThreadName
{
get
{
lock (this)
{
return threadName;
}
}
}
// for override constructor in derived classes
public ThreadWrapper()
{
}
public ThreadWrapper(string threadName)
{
this.threadName = threadName;
}
public virtual void Run()
{
}
public virtual void Terminate()
{
lock (this)
{
Terminated = true;
}
}
public void Start()
{
lock (this)
{
if (_thread == null)
{
_thread = new Thread(Run);
_thread.Start();
}
}
}
}
Then i create derived class from ThreadWrapper:
public delegate void ProcessMessageDelegate(string message);
public class Reader : ThreadWrapper
{
private ProcessMessageDelegate ProcessMessage;
public Reader(ProcessMessageDelegate processMessage)
: base()
{
this.ProcessMessage = processMessage;
}
public override void Run()
{
// Do something
}
}
Also i have Form with two buttons. The first button for start thread, the second button for "self-terminate" thread.
public partial class MainForm : Form
{
private MyReader Reader;
public MainForm()
{
InitializeComponent();
}
// real method for delegate
private void ProcessMessage(string message)
{
// add line to RichEdit
this.AddSpRRecordLog(message);
}
private void buttonRunTest_Click(object sender, EventArgs e)
{
if (MyReader == null)
{
MessageBox.Show("Wrong!");
return;
}
MyReader.Start();
}
private void buttonStopTest_Click(object sender, EventArgs e)
{
if (MyReader == null)
{
MessageBox.Show("Wrong!");
return;
}
MyReader.Terminate();
}
private void MainForm_Load(object sender, EventArgs e)
{
Reader MyReader = new Reader(new ProcessMessageDelegate(ProcessMessage));
}
If i use this way (create MyReader on FormLoad event) - MyReader does not create. If i create read in buttonRunTest_Click then everything is ok, but in this case i can't terminate MyReader.
This declares a local variable called MyReader that hides the MyReader field:
private void MainForm_Load(object sender, EventArgs e)
{
Reader MyReader = new Reader(new ProcessMessageDelegate(ProcessMessage));
}
Instead, just assign to the field:
private void MainForm_Load(object sender, EventArgs e)
{
MyReader = new Reader(new ProcessMessageDelegate(ProcessMessage));
}
(Incidentally, this isn't a global variable in the conventional sense - if another instance of MainForm is created, it would have its own independent MyReader field)

Categories