I have one MainForm (with dataGridView) and DataModule class with my own LoadDataTable method which execute FbCommand select sql and fill datatable in dataset and FbRemoteEvent catch method. When I run my app, in MainForm_OnLoad I call LoadDataTable method and my dataGridView show data successfully. But when my app catch FbRemoteEvent from server and call LoadDataTable method, exception occurred in dataGridView. Why?
MainForm:
public partial class MainForm : Form
{
private readonly DataModule _dataModule = DataModule.GetInstance();
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource = _dataModule.AppDataSet;
dataGridView1.DataMember = "MESSAGEQUEUE";
_dataModule.LoadMessageQueueDataTable();
}
}
DataModule:
private void FirebirdRemoteEventOnRemoteEventCounts(object sender, FbRemoteEventEventArgs fbRemoteEventEventArgs)
{
switch (fbRemoteEventEventArgs.Name.Trim().ToUpper())
{
case "QUEUE_NEW_MESSAGE":
if (fbRemoteEventEventArgs.Counts > 0)
{
LoadMessageQueueDataTable();
}
break;
}
}
public void LoadMessageQueueDataTable()
{
if (ConnectToFirebird())
{
using (var firebirdTransaction = FirebirdConnection.BeginTransaction())
{
using (var firebirdCommand = new FbCommand
{
Connection = firebirdTransaction.Connection,
Transaction = firebirdTransaction,
CommandType = CommandType.Text,
CommandText = "select MESSAGEQUEUEID, CREATEDATETIME, SENDER, RECIPIENT, TEXT from MESSAGEQUEUE"
})
{
AppDataSet.Tables["MESSAGEQUEUE"].Clear();
try
{
AppDataSet.Tables["MESSAGEQUEUE"].Load(firebirdCommand.ExecuteReader());
firebirdCommand.Transaction.Commit();
}
catch (FbException firebirdException)
{
firebirdCommand.Transaction.Rollback();
}
}
}
}
}
Error:
In DataModule class add and change FbRemoteEvent handler:
public delegate void DelegateMessageQueueTableUpdate();
public event DelegateMessageQueueTableUpdate MessageQueueTableUpdate;
private void FirebirdRemoteEventOnRemoteEventCounts(object sender, FbRemoteEventEventArgs fbRemoteEventEventArgs)
{
switch (fbRemoteEventEventArgs.Name.Trim().ToUpper())
{
case "QUEUE_NEW_MESSAGE":
if (fbRemoteEventEventArgs.Counts > 0)
{
if (MessageQueueTableUpdate != null)
{
MessageQueueTableUpdate();
}
}
break;
}
}
In MainForm:
public partial class MainForm : Form
{
private readonly DataModule _dataModule = DataModule.GetInstance();
private delegate void RefreshMessageQueueTable();
public MainForm()
{
InitializeComponent();
_dataModule.MessageQueueTableUpdate += () =>
{
if (dataGridView1.InvokeRequired)
{
dataGridView1.Invoke(new RefreshMessageQueueTable(_dataModule.LoadMessageQueueDataTable));
}
else
{
_dataModule.LoadMessageQueueDataTable();
}
};
}
private void MainForm_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = _dataModule.AppDataSet;
dataGridView1.DataMember = "MESSAGEQUEUE";
_dataModule.LoadMessageQueueDataTable();
}
}
Related
I'm working on a C# app,that searches for song names on youtube (using youtube api) and displaying the data, I have a custom SongItem (UserControl) and I add them to a FlowLayoutControl. I added a "Favourite" button to the UserControl, and I need that to add itself to another FlowLayoutControl that's the Favourited song list, but I can't get that working, I can't have multiple base classes in the UserControl,and adding a public method to Form1, doesn't solve my issue, (it's not adding anything,tried it with listbox,but nothing).
I'm really stuck here,if someone can at least suggest something I would rly appreciate it.
Here is my SongItem
[Serializable]
public partial class SongItem : UserControl,Form
{
private String songName = "Song Name";
private String artistName = "Artist Name";
private Image thumbNail;
private String length;
private int maxLengthSongName = 25;
private int maxLengthArtistName = 25;
private Color colorHoverOn = Color.FromArgb(53,53,53);
private Color colorNormal = Color.FromArgb(53,53,53);
private SongData songData;
public SongItem()
{
InitializeComponent();
this.MouseClick += Control_MouseClick;
MouseEvents(this);
}
private void SongItem_Load(object sender, EventArgs e)
{
try
{
LoadData();
}
catch { }
LoadDataToUI();
}
#region GettersAndSetters
public int MaxLengthSongName
{
get { return maxLengthSongName; }
set { maxLengthSongName = value; }
}
public int MaxLengthArtistName
{
get { return maxLengthArtistName; }
set { maxLengthArtistName = value; }
}
public Color ColorHoverOn
{
get { return colorHoverOn; }
set { colorHoverOn = value; }
}
public Color ColorNormal
{
get { return colorNormal; }
set { colorNormal = value; }
}
public SongData SongData {
get{return songData; }
set { songData = value; }
}
#endregion
public void LoadData()
{
songName = songData.SongName;
artistName = songData.ArtistName;
thumbNail = songData.ThumbNail;
length = songData.Length;
}
void MouseEvents(Control container)
{
foreach (Control c in container.Controls)
{
c.MouseEnter += (s, e) => SongItem_MouseEnter(e);
c.MouseLeave += (s, e) => SongItem_MouseLeave(e);
c.MouseClick += Control_MouseClick;
MouseEvents(c);
};
}
private void SongNameLbl_MouseHover(object sender, EventArgs e)
{
if (songName.Length > maxLengthSongName) {
toolTip1.SetToolTip(songNameLbl, songName);
}
}
private void ArtistNameLbl_MouseHover(object sender, EventArgs e)
{
if (artistName.Length > maxLengthArtistName) {
toolTip1.SetToolTip(artistNameLbl, artistName);
}
}
private void SongNameLbl_Click(object sender, EventArgs e)
{
Clipboard.SetText(artistName + " " +songName);
}
#endregion
#region CurrentlySelected
public event EventHandler<EventArgs> WasClicked;
private void Control_MouseClick(object sender, MouseEventArgs e)
{
var wasClicked = WasClicked;
if (wasClicked != null)
{
WasClicked(this, EventArgs.Empty);
}
IsSelected = true;
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
this.BorderStyle = IsSelected ? BorderStyle.FixedSingle : BorderStyle.None;
}
}
#endregion
private void Fovourite_Click(object sender, EventArgs e)
{
Main newMain = new Main();
// newMain.AddSongToFavorite();
newMain.listBox1.Items.Add("Test");
}
}
}
Here is the the Form1 code
public void AddSongToFavorite() {
listBox1.Items.Add("Test");
//songList2.AddSong("Dire Straits - Sultans Of Swing");
MessageBox.Show("Hello", "Test");
// flowLayoutPanel1.Controls.Add(song);
}
Message shows up,but nothing else
I add the SongItem from another class
public partial class SongList : FlowLayoutPanel
{
public SongList()
{
InitializeComponent();
SongList_Load();
}
private void SongList_Load()
{
this.AutoScroll = true;
this.FlowDirection = FlowDirection.TopDown;
this.AutoSize = false;
this.WrapContents = false;
}
public async void AddSong(String songName) {
SongData song = await YoutubeSearch.GetSongInfo(songName);
// SongData song = XmlSerialization.ReadFromXmlFile<SongData>(Application.StartupPath + #"\test.txt");
SongItem songItem = new SongItem { SongData = song };
songItem.WasClicked += UsersGrid_WasClicked;
this.Controls.Add(songItem);
}
I fixed the problem by creating an EventHandler
In the main I created this public void
public void FavoriteWasClicked(object sender, EventArgs e) {
if (sender is SongItem)
{
songList2.AddSong(((SongItem)sender).SongData);
}
}
and on Form1 load I added (songList1 is the FlowLayoutPanel already added in the Form1 designer)
songList1.List_FavoriteWasClicked += FavoriteWasClicked;
I added this line to the FlowLayoutPanel class I created
public event EventHandler<EventArgs> List_FavoriteWasClicked;
and when creating new Controls(SongItems inside it)(Still part of FlowLayoutPanel)
public void AddSong(SongData song)
{
SongItem songItem = new SongItem { SongData = song };
songItem.FavoriteWasClicked += List_FavoriteWasClicked; ()
this.Controls.Add(songItem);
}
And now on the SongItem I created the custom event
public event EventHandler<EventArgs> FavoriteWasClicked;
and on the button I wanted to be the press to add to favorite list I added the following
FavoriteWasClicked(this, EventArgs.Empty);
Now when I press the button to add one Song to the liked/favorited list it's actually adding it.
So, I got kind of stuck over my head while I tried to program something new.
I'm trying to add objectBeer_pluche or objectBeer_Elektro to my OBJberenlijst on the Beren Main form from the details Form, so I can add both instances of 2 classes to the same list.
I'm not even sure this is possible by the way. So, I would like feedback if what I am trying to do is possible to start with. I already figured VOID is not right but I am really clueless here.
This is my main beren.cs form with an OBJberenlist, that's where I try to add objectBeer_pluche or objectBeer_Elektro into it:
public partial class Beren : Form
{
public interface Berenlijst { }
public List<Berenlijst> OBJberenLijst = new List<Berenlijst>();
public Beren()
{
InitializeComponent();
}
private void Beren_Load(object sender, EventArgs e)
{
}
private void BTNToevoegen_Click(object sender, EventArgs e)
{
this.Hide();
Details Details = new Details();
if (Details.ShowDialog(this) == DialogResult.OK)
{
OBJberenLijst.Add(Details.getdetails());
}
Details.Close();
Details.Dispose();
}
public void LijstLaden()
{
foreach(Beer berenobject in OBJberenLijst)
{
LST_beren.Items.Add(berenobject.Naam);
}
}
}
}
from this form called details.cs
public partial class Details : Form
{
public Details()
{
InitializeComponent();
BTN_toevoegen.DialogResult = DialogResult.OK;
BTN_cancel.DialogResult = DialogResult.Cancel;
}
private void Details_Load(object sender, EventArgs e)
{
RDB_pluche.Checked = true;
BTN_ok.Enabled = false;
}
private void RDB_pluche_CheckedChanged(object sender, EventArgs e)
{
PANEL_pluche.Visible = true;
PANEL_elektro.Visible = false;
}
private void RDB_elektro_CheckedChanged(object sender, EventArgs e)
{
PANEL_pluche.Visible = false;
PANEL_elektro.Visible = true;
}
private void BTN_toevoegen_Click(object sender, EventArgs e)
{
open_foto.Filter = "jpg (*.jpg)|*.jpg|bmp(*.bmp)|*.bmp|png(*.png)|*.png";
if (open_foto.ShowDialog() == System.Windows.Forms.DialogResult.OK && open_foto.FileName.Length > 0)
{
TXT_adres.Text = open_foto.FileName;
PIC_beer.Image = Image.FromFile(open_foto.FileName);
}
}
private void BTN_ok_Click(object sender, EventArgs e)
{
}
public void getdetails()
{
if (RDB_pluche.Enabled == true)
{
Pluche_Beer objectBeer_pluche = new Pluche_Beer(TXTNaam_pluche.Text, open_foto.FileName, "(Wasprogramma: " + TXT_wasprogramma.ToString() + " Graden Celsius");
}
else
{
Elektronische_Beer objectBeer_Elektro = new Elektronische_Beer(TXTNaam_elekro.Text, open_foto.FileName, "aantal Batterijen: " + CMBOBatterijen.ToString());
}
}
private void Details_MouseMove(object sender, MouseEventArgs e)
{
foreach (Control c in this.Controls)
{
if (c is TextBox)
{
TextBox textBox = c as TextBox;
if (textBox.Text != string.Empty)
{
BTN_ok.Enabled = true;
}
}
}
}
}
}
The problem is between this line...
OBJberenLijst.Add(Details.getdetails());
...and this line.
public void getdetails()
List.Add() requires an object to add, but getdetails() returns void. You probably want to change getdetails() to something like the following:
public Berenlijst getdetails()
{
if (RDB_pluche.Enabled == true)
{
return new Pluche_Beer(TXTNaam_pluche.Text, open_foto.FileName, "(Wasprogramma: " + TXT_wasprogramma.ToString() + " Graden Celsius");
}
return new Elektronische_Beer(TXTNaam_elekro.Text, open_foto.FileName, "aantal Batterijen: " + CMBOBatterijen.ToString());
}
Hopefully Pluche_Beer and Elektronisch_Beer inherent from Berenlijst. Otherwise you'll have to revise your logic in a broader way.
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();
}
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();
}
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)