Passing list of objects to main form - winforms

I have the main form Form1 which opens when I run the app. I pass a list from this form which contains Supplier objects to a secondary Form2, to help me build Product objects using an attribute of objects stored in the Suppliers list in Form1.
In Form2 I have the list of Product objects which I want to pass back to Form1 after i complete it and show it in a ListView. But something is not working..i don't figure out what. Thank you in advance.
Form1:
public partial class Form1 : Form
{
public ArrayList suplist = new ArrayList(); //suppliers list
public List<Product> productlist = new List<Product>(); //products list which will be populated with objects sent from Form2
public Form1()
{
InitializeComponent();
//Read Suppliers from txt
StreamReader sr = new StreamReader("Suppliers.txt");
string linie = null;
while((linie=sr.ReadLine())!=null) {
try
{
int id = Convert.ToInt32(linie.Trim().Split(',')[0]);
string nume = linie.Trim().Split(',')[1];
Supplier sp = new Supplier(id, nume);
suplist.Add(sp);
}
catch(Exception ex) { MessageBox.Show(ex.Message); }
}
listView1.Columns.Add("ID");
listView1.Columns.Add("Nume");
listView1.Columns.Add("Units");
listView1.Columns.Add("Price");
listView1.Columns.Add("SUpplier Id");
}
private void button1_Click(object sender, EventArgs e)
{
Form2 from = new Form2(suplist);
from.ShowDialog();
}
public List<Product> ProductList
{
get { return productlist; }
set { productlist = value; }
}
private void button2_Click(object sender, EventArgs e)
{ //this function is supposed to populate listview with the productlist objects when i click the button;
//not sure if it is wrong writeed, or passing the list of products created in Form2 failed
foreach (Product p in productlist)
{
//listView1.Items.Add(p.Id);
ListViewItem itm = new ListViewItem(p.Id.ToString());
itm.SubItems.Add(p.Nume);
itm.SubItems.Add(p.Units.ToString());
itm.SubItems.Add(p.Price.ToString());
itm.SubItems.Add(p.SupplierId.ToString());
}
}
}
Form2:
public partial class Form2 : Form
{
public List<Product> prodList = new List<Product>(); //list which stores the Products == > the list i want to send back to Form 1
public ArrayList supplierList = new ArrayList(); //list of suppliers received from From 1, used to build Products objects
public Form2(ArrayList suplist)
{
InitializeComponent();
supplierList = suplist;
foreach(Supplier s in supplierList)
{
comboBox1_supID.Items.Add(s.Id);
}
Product p1 = new Product(1, "Cola", 4, 45, 1);
Product p2 = new Product(2, "Fanta", 32, 22, 2);
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1__id.Text == "") errorProvider1.SetError(textBox1__id, "Introduceti id");
else if (textBox2_nume.Text == "") errorProvider1.SetError(textBox2_nume, "Introduceti numele");
else if (textBox3_units.Text == "") errorProvider1.SetError(textBox3_units, "Introduceti units");
else if (textBox4_price.Text == "") errorProvider1.SetError(textBox4_price, "enter price");
else if (comboBox1_supID.Text == "") errorProvider1.SetError(comboBox1_supID, "Select sup id");
else
try
{
int id = Convert.ToInt32(textBox1__id.Text);
string nume = textBox2_nume.Text;
int units = Convert.ToInt32(textBox3_units.Text);
double price = Convert.ToDouble(textBox4_price.Text);
int supid = Convert.ToInt32(comboBox1_supID.Text);
Product pd = new Product(id, nume, units, price, supid);
prodList.Add(pd);
MessageBox.Show("Produs adaugat cu succes");
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
textBox1__id.Clear();
textBox2_nume.Clear();
textBox4_price.Clear();
textBox3_units.Clear();
errorProvider1.Clear();
}
}
private void textBox4_price_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsDigit(e.KeyChar))
{
errorProvider1.SetError(textBox4_price, "Introduceti numai cifre");
}
else errorProvider1.Clear();
}
private void button2_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
frm.productlist = prodList;
frm.Show();
}
}
I want to send to Form1 prodList from Form2, (store it in productlist i guess in Form1) and show them in listview1 in Form1.
On short, in Form1 I create Suppliers, store them in suplist and pass this list to Form2(in supplierlist). In Form2 I create Products, store them in prodList and pass it to Form1(in productList). Why isn't working? and why listview doesn't show anything??

I haven't worked yet with the ListView-Object itself yet but I think you missed to add the created ListViewItem to your ListView
foreach (Product p in productList)
{
ListViewItem itm = new ListViewItem(p.Id.ToString());
itm.SubItems.Add(p.Nume);
itm.SubItems.Add(p.Units.ToString());
itm.SubItems.Add(p.Price.ToString());
itm.SubItems.Add(p.SupplierId.ToString());
listView1.Items.Add(itm);
}

Related

WPF: store objects inside application settings.settings file

I build a simple ClipboardManager that hold all last Copy item.
So i have this simple ClipboardItem class:
public class ClipboardItem : INotifyPropertyChanged
{
private string _text { get; set; }
private int _index { get; set; }
public string Text
{
get { return _text; }
set
{
_text = value;
NotifyPropertyChanged();
}
}
public int Index
{
get { return _index; }
set
{
_index = value;
NotifyPropertyChanged();
}
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
And my ViewModel class that hold ObservableCollection<ClipboardItem>:
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<ClipboardItem> _clipboards;
public ViewModel()
{
if (_clipboards == null)
{
_clipboards = new ObservableCollection<ClipboardItem>();
_clipboards.CollectionChanged += _clipboards_CollectionChanged;
}
}
private void _clipboards_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
for (int i = 0; i < _clipboards.Count; i++)
_clipboards[i].Index = i + 1;
}
public ObservableCollection<ClipboardItem> Clipboards
{
get { return _clipboards; }
set
{
_clipboards = value;
NotifyPropertyChanged();
}
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
So every Copy create new ClipboardItem object inside list but when i restart the application all the records gone so i wonder if there any way to store all my ClipboardItem object inside the application settings.settings file.
//Variable Creation
private string _dataFileName = #"ClipData.xml";
DataTable _clipDataTable = new DataTable();
Inside ViewModel constructor.
public ViewModel()
{
if (_clipboards == null)
{
_clipboards = new ObservableCollection<ClipboardItem>();
_clipboards.CollectionChanged += _clipboards_CollectionChanged;
}
InitDataTable();
ReadDataFile();
}
Create new Methods
/// <summary>
/// Initialize Data Table considering you have only 1 column data.
/// If you have more then you need to create more columns
/// </summary>
private void InitDataTable()
{
_clipDataTable = new DataTable();
_clipDataTable.Columns.Add("ClipHeader");
_clipDataTable.AcceptChanges();
}
//the clipboard Data is saved in xml file.
private void WriteDataFile()
{
DataSet ClipDataSet = new DataSet();
ClipDataSet.Tables.Add(_clipDataTable);
ClipDataSet.WriteXml(_dataFileName);
}
// if file exits then read the xml file and add it to the Collection, which will be reflected in UI.
private void ReadDataFile()
{
DataSet ClipDataSet = new DataSet();
if (File.Exists(_dataFileName))
{
ClipDataSet.ReadXml(_dataFileName);
foreach (DataRow item in ClipDataSet.Tables[0].Rows)
{
Clipboards.Add(new ClipboardItem { Text = Convert.ToString(item["ClipHeader"]) });
}
}
}
Using Command you can bind Method of ViewModel to Window Closing event. So whenever the user closes the window, the data in the collection will be written into the Xml file.
Data from the Collection is copied into DataTable.
private void WindowCloseCommadn(object o)
{
foreach (var item in Clipboards)
{
DataRow dataRow = _clipDataTable.NewRow();
dataRow["ClipHeader"] = item.Text;
_clipDataTable.Rows.Add(dataRow);
}
WriteDataFile();
}
Update:-
Same Code without ViewModel, by making the codebehind class has the DataContext for binding Collection.
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ClipboardMonitor clipboardMonitor;
private string _dataFileName = #"ClipData.xml";
DataTable _clipDataTable = new DataTable();
public ObservableCollection<ClipboardItem> Clipboards { get; set; }
public MainWindow()
{
InitializeComponent();
Clipboards = new ObservableCollection<ClipboardItem>();
Clipboards.CollectionChanged += Clipboards_CollectionChanged;
Loaded += MainWindow_Loaded;
InitiateClipboardMonitor();
this.Closing += MainWindow_Closing1;
this.DataContext = this;
}
private void MainWindow_Closing1(object sender, CancelEventArgs e)
{
foreach (var item in Clipboards)
{
DataRow dataRow = _clipDataTable.NewRow();
dataRow["ClipHeader"] = item.Text;
_clipDataTable.Rows.Add(dataRow);
}
WriteDataFile();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
InitDataTable();
ReadDataFile();
}
/// <summary>
/// Initialize Data Table considering you have only 1 column data.
/// If you have more then you need to create more columns
/// </summary>
private void InitDataTable()
{
_clipDataTable = new DataTable();
_clipDataTable.Columns.Add("ClipHeader");
_clipDataTable.AcceptChanges();
}
private void WriteDataFile()
{
DataSet ClipDataSet = new DataSet();
ClipDataSet.Tables.Add(_clipDataTable);
ClipDataSet.WriteXml(_dataFileName);
}
private void ReadDataFile()
{
DataSet ClipDataSet = new DataSet();
if (File.Exists(_dataFileName))
{
ClipDataSet.ReadXml(_dataFileName);
foreach (DataRow item in ClipDataSet.Tables[0].Rows)
{
Clipboards.Add(new ClipboardItem { Text = Convert.ToString(item["ClipHeader"]) });
}
}
}
private void Clipboards_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
for (int i = 0; i < Clipboards.Count; i++)
{
Clipboards[i].Index = i + 1;
}
}
private void InitiateClipboardMonitor()
{
clipboardMonitor = new ClipboardMonitor();
clipboardMonitor.OnClipboardContentChanged += ClipboardMonitor_OnClipboardContentChanged; ;
}
private void ClipboardMonitor_OnClipboardContentChanged(object sender, EventArgs e)
{
string clipboardText = Clipboard.GetText(TextDataFormat.Text);
Clipboards.Add(new ClipboardItem { Text = clipboardText });
}
}
to know about Command, refer the article
https://www.codeproject.com/Articles/274982/Commands-in-MVVM

How to automatically refresh listbox when add or remove the item in WPF?

I have WPF application that uses web service (asmx). The web service uses EF to get the data from MS SQL Server.
The code looks as following:
1) WPF:
public partial class MainWindow : Window
{
LetterWebServiceSoapClient _client = new LetterWebServiceSoapClient();
private ObservableCollection<Letter> _letters;
public MainWindow()
{
InitializeComponent();
}
private void cmdGetLetters_Click(object sender, RoutedEventArgs e)
{
lstLetters.ItemsSource = null;
_letters = _client.GetAllLetters();
lstLetters.ItemsSource = _letters;
}
private void cmdDeleteLetter_Click(object sender, RoutedEventArgs e)
{
_client.DeleteLetter((Letter)lstLetters.SelectedItem);
}
private void cmdAddLetter_Click(object sender, RoutedEventArgs e)
{
var newLetter = new Letter
{
Name = "Letter3",
Date = DateTime.Now,
Recipient = "John",
Sender = "David",
Content = "cccc"
};
_client.AddNewLetter(newLetter);
}
}
2) The web service:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class LetterWebService : System.Web.Services.WebService
{
LetterDbEntities _letterDbEntities = new LetterDbEntities();
[WebMethod]
public ObservableCollection<Letter> GetAllLetters()
{
return new ObservableCollection<Letter>(_letterDbEntities.Letters.ToList());
}
[WebMethod]
public void AddNewLetter(Letter newLetter)
{
_letterDbEntities.Letters.Add(newLetter);
_letterDbEntities.SaveChanges();
}
[WebMethod]
public void DeleteLetter(Letter letter)
{
var letterToBeDeleted = _letterDbEntities.Letters.First(l => l.Id == letter.Id);
_letterDbEntities.Letters.Remove(letterToBeDeleted);
_letterDbEntities.SaveChanges();
}
}
When I add new letter or remove existing one they are added or removed on database level, but it doesn't reflect in UI that is in list box. What I'm missing?
You need to change the _letters collection. Try this:
private void cmdDeleteLetter_Click(object sender, RoutedEventArgs e)
{
var selectedItem = (Letter)lstLetters.SelectedItem;
_client.DeleteLetter(selectedItem);
_letters.Remove(selectedItem);
}
private void cmdAddLetter_Click(object sender, RoutedEventArgs e)
{
var newLetter = new Letter
{
Name = "Letter3",
Date = DateTime.Now,
Recipient = "John",
Sender = "David",
Content = "cccc"
};
_client.AddNewLetter(newLetter);
_letters.Add(newLetter);
}

Cannot set the value of a global variable

Im pretty new to programming, but im very eager to get more into this stuff, and in particular, c#. I have a made some code for an autotyper (spam bot if i may), only to be used as a goal for me to create. Essentially, what i want the program to do, is as following:
When i start my Form1, the global variable "_timerValue" is set to
1000
When i hit Start button, the text from the textbox on will be sent at
the interval of "_timerValue"
When i hit the Speed button, Form2 will show.
When i hit very fast, "_timerValue" is set to 5000 (testing purposes)
Form1 code:
public partial class Form1 : Form
{
static class TimerIntervalValue
{
Form2 f2 = new Form2();
TimerIntervalValue = f2._timerValue;
}
public Form1()
{
InitializeComponent();
f2._timerValue = "1000";
}
public void timer1_Tick(object sender, EventArgs e)
{
SendKeys.Send(textBox1.Text);
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show(f2._timerValue);
timer1.Interval = Convert.ToInt32(f2._timerValue);
if (timer1.Enabled == false)
{
timer1.Enabled = true;
textBox1.Enabled = false;
button1.Text = ("Stop");
}
else if (timer1.Enabled == true)
{
timer1.Enabled = false;
textBox1.Enabled = true;
button1.Text = ("Start");
}
}
private void button2_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.Show();
}
}
Form2 code:
public partial class Form2 : Form
{
public string TimerValue;
public string _timerValue
{
get { return TimerValue; }
set { TimerValue = value; }
}
public Form2()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2._timerValue = "5000";
}
}
I originally tried to create a Form2 instance just under "InitializeComponent();" in Form1, but that didnt seem to be accessible through the other funtions.
I just know its something very simple like im using the wrong class to create the Form2 instance or something like that ...
Anyway, thank you in advance
Just mark TimerValue and _timerValue as static. Then you don't need to use
Form2 f2 = new Form2(); or Form2 frm2 = new Form2();
anymore. In Form 1, just use Form2._timerValue instead of f2._timerValue. In Form 2, just change:
public void button1_Click(object sender, EventArgs e)
{
_timerValue = "5000";
}

get selected item id from datagrid filled by database WPF

My question was how to get the item or value of a selecteditem out of my datagrid that gets filled by a obc of my view. From te result that i get it seems i need to cast it but all the casts i found from google and here are not working.
Anyone got some tips or solution?
public partial class req: Page
{
DataClasses1DataContext dc = new DataClasses1DataContext();
public requests()
{
InitializeComponent();
//get from Database View
var query = from r in dc.requestViews select r;
this.gridRequest.ItemsSource = new ObservableCollection<requestView>(query);
this.gridRequest.ColumnWidth = 122.7;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (gridRequest.SelectedItem == null)
{
MessageBox.Show("Select a Order!");
}
else
{
var qres = (from r in dc.orders where r.id.Equals(gridRequest.SelectedValue) select r).FirstOrDefault();
qres.order_status_id = 3;
dc.SubmitChanges();
MessageBox.Show("Request Accepted");
this.NavigationService.Refresh();
}
}

Updating controls in child form from parent form

I have below code in Form2
public void authorisedList()
{
using (myContext v = new myContext())
{
DateTime date = DateTime.Today.AddMonths(-12);
var myList = (from l in v.AuthorisedList
where l.FromDate >= date
select new
{
l.ID,
l.EmpName,
l.StartDate,
l.EndDate,
l.Days,
l.Approved,
l.Confirmed,
}).ToList();
reportViewer1.LocalReport.DataSources.Clear();
ReportDataSource datasource = new ReportDataSource("MyReportsDatasource", myList);
reportViewer1.LocalReport.DataSources.Add(datasource);
string exeFolder = Path.GetDirectoryName(Application.ExecutablePath);
string reportPath = Path.Combine(exeFolder, #"rdlcReports\Authorised List.rdlc");
reportViewer1.LocalReport.ReportPath = reportPath;
reportViewer1.RefreshReport();
}
}
Then in Form1 which is a parent of Form2, i have below code in radiobutton
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
Form2 au = new Form2(this);
au.authorisedList();
}
The problem is that when i check a radioButton control (radioButton1) in Form1, authorisedList() in Form2 seems to be executing but the reportViewer report does not update/change.
Am wondering why.
If your Form2 is already open , then you should get the object of the open form and then call its authorisedList() method. You can use Application.OpenForms property.
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
Form2 au = Application.OpenForms["Form2"] as Form2;
if(au != null)
au.authorisedList();
}

Resources