How to add to List Generic on each button clicks - c#

I have a button that gets items from controls and add to a list.
As shown
This is my ojects thats holds the values.
public class SelectedPurchaseItems
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public double PurchasePrice { get; set; }
public int Quantity { get; set; }
public string UnitOfMeasure { get; set; }
public double Total { get; set; }
}
This is my mainwindow class that does the adding to the list
public partial class MainWindow : Window
{
public List<SelectedPurchaseItems> SelectedList;
private void btnSaveModalSelectItem_Click(object sender, RoutedEventArgs e)
{
SelectedList = new List<SelectedPurchaseItems>();
SelectedPurchaseItems _value = new SelectedPurchaseItems()
{
ItemId = Convert.ToInt32(comboboxSelectItemItem.SelectedValue),
ItemName = comboboxSelectItemItem.Text,
PurchasePrice = _purchasePrice,
Quantity = _quantity,
UnitOfMeasure = comboboxSelectItemUnitofMeasure.Text,
Total = _total
};
SelectedList.Add(_value);
DataGridSelectedPurchaseItems.ItemsSource = SelectedList;
}
}
My challenge now is, any time it adds an item to the List, it always reinitialize the list, which makes the previous item added to clear off.
But my aim is for the List to hold each item that has been added to it, and i don't know how to go about that.
I'm also Binding the list to a WPF datagrid. So after showing the first added item, it won't display any further added item.

SelectedList = new List<SelectedPurchaseItems>();
is the line that reinitializes your list. You should just delete it, and move initial list initialization to a constructor or somwhere else

Dont re-instantiate it in the button click. Simply initialise it once as shown:
public partial class MainWindow : Window
{
public List<SelectedPurchaseItems> SelectedList = new List<SelectedPurchaseItems>();
public MainWindow()
{
DataGridSelectedPurchaseItems.ItemsSource = SelectedList;
}
private void btnSaveModalSelectItem_Click(object sender, RoutedEventArgs e)
{
SelectedPurchaseItems _value = new SelectedPurchaseItems()
{
ItemId = Convert.ToInt32(comboboxSelectItemItem.SelectedValue),
ItemName = comboboxSelectItemItem.Text,
PurchasePrice = _purchasePrice,
Quantity = _quantity,
UnitOfMeasure = comboboxSelectItemUnitofMeasure.Text,
Total = _total
};
SelectedList.Add(_value);
}
}

Related

How to show members of a list in listbox when selected in WPF

I'm fairly new to programming, so please forgive my ignorance.
I have 2 classes and 2 listboxes in my WPF app for adding patients and wards. One of my classes (Ward) includes a list of the other class (Patients) as a property.
I've figured out how to add patients to a ward as a list. Now the part I'm struggling with: I need to be able to add the patients to a particular ward based on the ward that is selected in that ward list, and also show the patients of that ward in a separate listbox.
I created a selection changed event so that when a ward is selected, the patients will show. I just don't know how to change the source of the second listbox to the wards' patients.
I've attached the code and a screenshot of the app below. Any help getting this to work is really appreciated. Thanks.
Screenshot: [1]: https://i.stack.imgur.com/omILR.png
public partial class MainWindow : Window
{
public ObservableCollection<Ward> ward = new ObservableCollection<Ward>();
public ObservableCollection<Patient> patient = new ObservableCollection<Patient>();
public MainWindow()
{
InitializeComponent();
}
private void sliderCapacity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
tblkCapacity.Text = string.Format("{0:F0}", sliderCapacity.Value);
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
btnAddWard.IsEnabled = false;
btnAddPatient.IsEnabled = false;
Ward w1 = new Ward("Marx Brothers", 3);
Ward w2 = new Ward("Addams Family", 7);
ward.Add(w1);
ward.Add(w2);
Patient p1 = new Patient("Chico", 67, BloodType.A);
Patient p2 = new Patient("Graucho", 57, BloodType.AB);
Patient p3 = new Patient("Harpo", 46, BloodType.B);
w1.Patients.Add(p1);
w1.Patients.Add(p2);
w1.Patients.Add(p3);
//display on screen
lbxWards.ItemsSource = ward;
//begin ward list count at 2
Ward.NumberOfWards++;
Ward.NumberOfWards++;
int totalWards = Ward.NumberOfWards;
tblkNumberOfWards.Text = string.Format("({0})", totalWards);
}
private void lbxWards_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//need to make patients listbox (lbxPatients) populate with patients of selected ward when hovered
}
Patient Class:
public class Patient
{
public string PatientName { get; set; }
public DateTime DOB { get; set; }
public static int Age { get; set; }
public BloodType BloodType { get; set; }
public static int NumberOfPatients { get; set; }
public Patient(string patientName, DateTime dob, int age, BloodType bloodType)
{
PatientName = patientName;
DOB = dob;
Age = age;
BloodType = bloodType;
}
public Patient(string patientName, int age, BloodType bloodType)
{
PatientName = patientName;
Age = age;
BloodType = bloodType;
}
public Patient()
{
}
public override string ToString()
{
return string.Format("{0} ({1}) Type: {2}", PatientName, Age, BloodType);
}
}
Ward Class
public class Ward
{
public List<Patient> Patients { get; set; }
public string WardName { get; set; }
public double Capacity { get; set; }
public static int NumberOfWards { get; set; }
public Ward(string wardName, double capacity)
{
WardName = wardName;
Capacity = capacity;
Patients = new List<Patient>();
}
public Ward()
{
Patients = new List<Patient>();
}
public override string ToString()
{
return string.Format("{0} Ward \t (Limit: {1})", WardName, Capacity);
}
}
Use MVVM instead of code-behind. Give your main window a DataContext of MainWindowViewModel. Like this
// BaseViewModel class for implementing INotifyPropertyChanged.
// This is a terribly simple implementation. There are better ones.
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected RaisePropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name);
}
// MainWindowViewModel. An instance of this should be set, at startup as
// the DataContext of the MainWindow
public class MainWindowViewModel : BaseViewModel
{
public ObservableCollection<Ward> Wards { get; } = new();
private Ward _currentWard;
public Ward CurrentWard
{
get => _currentWard;
set
{
if (value == _currentWard)
return;
// Current ward changed. Raise the event.
_currentWard = value;
RaisePropertyChanged(nameof(CurrentWard));
}
}
}
Then your XAML in MainWindow might look something like this (I'm supposing a grid with rows and columns. I'm also supposing that the current default DataContext of this XAML is an instance of MainWindowViewModel
<!-- Main list of wards on the left -->
<ListBox x:Name="WardListBox"
ItemsSource="{Binding Wards}"
SelectedItem="{Binding CurrentWard}"
Grid.Row="0" Grid.Column="0"
/>
<!-- List of patients in the currently selected ward on the right -->
<ListBox x:Name="PatientListBox"
ItemsSource="{Binding CurrentWard.Patients}"
Grid.Row="0" Grid.Column="1"
/>

Displaying Item from Listbox onto Textbox

I am trying to display an item from a CSV file onto listbox(this part works) and then display individual parts of that item in separate labels.
public partial class InventoryForm : Form
{
public InventoryForm()
{
InitializeComponent();
}
public List<ItemsList> itemsLists(string csvPath)
{
var query = from l in File.ReadAllLines(csvPath)
let data = l.Split('|')
select new ItemsList
{
Name = data[0],
Type = data[1],
DMGTyp = data[2],
DMG = data[3],
Weight = int.Parse(data[4]),
Price = int.Parse(data[5]),
Description = data[5]
};
return query.ToList();
}
private void btnBrowse_Click(object sender, EventArgs e)
{
OpenFileDialog filePath = new OpenFileDialog();
filePath.ShowDialog();
textBox1.Text = filePath.FileName;
}
private void btnLoad_Click(object sender, EventArgs e)
{
listBox1.DataSource = itemsLists(textBox1.Text);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//to do show individual pieces in labels
}
public class ItemsList
{
public string Name { get; set; }
public string Type { get; set; }
public string DMGTyp { get; set; }
public string DMG { get; set; }
public int Weight { get; set; }
public int Price { get; set; }
public string Description { get; set; }
}
}
The items are broken up into 6 parts and the list box only shows the name of the item but I want the label to show the rest of the item's properties. Any clues on how to do that?

checking if datagrid has values

I am working on a C# project which includes WPF. I was wondering, If I could somehow check If my data grid contains certain element.
For example,
I have combo box whose itemsSource is some list of objects. Now, when an user selects an item from the combo box and presses the button
below in data grid (in same window) that item shows up.
I want to forbid the user to select same item more than once and for example put MessageBox with error message. How could I do that?
Code
This Window:
public partial class AvioWindowAddNEdit : Window
{
Avio avio;
public enum Stage { ADD, EDIT};
Stage stage;
public AvioWindowAddNEdit(Avio avio, Stage stage = Stage.ADD)
{
InitializeComponent();
this.avio= avio;
this.stage= stage;
textboxCode.DataContext = avio;
comboboxListofFlights.ItemsSource = Aplikacija.Instance.Flights;
comboboxListofFlights.DataContext = avio;
datagridListofFlights.ItemsSource = avio.ListofFlights;
datagridListofFlights.ColumnWidth = new DataGridLength(1, DataGridLengthUnitType.Auto);
if (stage== Stage.EDIT)
{
textboxCode.IsEnabled = false;
}
}
}
Button which adds selected item to data grid:
private void btnAddFlight_Click(object sender, RoutedEventArgs e)
{
avio.ListOfFlights.Add(comboboxListOfFlights.SelectedItem as Flight);
}
Singleton class for loading in all of my data:
class Aplication
{
public ObservableCollection<User> Users { get; set; }
public ObservableCollection<Airport> Airports { get; set; }
public ObservableCollection<Flight> Flights{ get; set; }
public ObservableCollection<Avio> Avios { get; set; }
public string LoggedInUser { get; set; }
private static Aplication instance = new Aplication();
public static Aplication Instance
{
get
{
return instance;
}
}
private Aplication()
{
Users= new ObservableCollection<User>();
Airports = new ObservableCollection<Airport>();
Flights = new ObservableCollection<Flight>();
Avios= new ObservableCollection<Avio>();
FillInData(); //method where I filled in all of these ObservableCollections
}
}
My class:
public class Avio : ObservableObject, ICloneable
{
//observableobject is an object where I implemented INotifyPropertyChanged
private string code;
public string Code
{
get { return code; }
set { code= value; OnPropertyChanged("Code"); }
}
private ObservableCollection<Flight> listOfFlights;
public ObservableCollection<Flight> ListOfFlights
{
get { return listOfFlights; }
set { listOfFlights= value; OnPropertyChanged("ListOfFlights"); }
}
private bool active;
public bool Active
{
get { return active; }
set { active= value; OnPropertyChanged("Active"); }
}
public Avio()
{
active= true;
ListOfFlights = new ObservableCollection<Flight>();
}
public Avio(string code)
{
active= true;
ListOfFlights = new ObservableCollection<Flight>();
Code= code;
}
}
You could use an ObservableCollection as an ItemsSource for your DataGrid. In that way you'll always have easy access to the data via code.
Check out this tutorial as a starting point (this uses ListBox instead of DataGrid, but it's easily adaptable to DataGrid).

Subset List of parent List not binding to Listbox in Winforms

I am trying to bind a List of a custom class to a Listbox and cannot get anything to display. The List is a subset of another List. I can bind the parent List and see the items, but not the child List. How can I get the subset List to bind to the Listbox? I have tried changing the order of the ListBox's DisplayMember, ValueMember, and DataSource properties. In debugging I can see that the DataSource has the correct values, but I can't get them to display. Relevant code below:
public class DimZone
{
public int Zone_Key { get; set; }
public int Zone_ID { get; set; }
public int Facility_Key { get; set; }
public string Zone_Name { get; set; }
public string Zone_Type { get; set; }
}
GlobalVariables Class containing global List collection:
public static List<DimZone>[] zoneCollection = new List<DimZone>[maxServerCount];
Form using global List collection and subset List:
List<DimZone> zoneCollectionAppended = new List<DimZone>();
private void StaffStatusReportForm_Load(object sender, EventArgs e)
{
facilityComboBox.DataSource = GlobalVariables.facilityCollection;
GetFacilityIndex();
CreateZoneAppendedList();
PopulateUI();
}
private void CreateZoneAppendedList()
{
foreach (var zone in GlobalVariables.zoneCollection[currentFacilityIndex])
{
if (zone.Zone_Name != "All")
{
zoneCollectionAppended.Add(zone);
}
}
}
private void PopulateUI()
{
if (zoneCollectionAppended != null)
{
zoneListBox.DisplayMember = "Zone_Name";
zoneListBox.ValueMember = "Zone_ID";
zoneListBox.DataSource = zoneCollectionAppended;
}
}
Your code contains various unclear parts. In any case, the best proceeding in these situations is setting up a properly-working simpler code and modifying it until reaching the stage you want. I can provide this properly-working first step. Sample code:
private void Form1_Load(object sender, EventArgs e)
{
List<DimZone> source = new List<DimZone>();
DimZone curZone = new DimZone() { Zone_Key = 1, Zone_ID = 11, Facility_Key = 111, Zone_Name = "1111", Zone_Type = "11111" };
source.Add(curZone);
curZone = new DimZone() { Zone_Key = 2, Zone_ID = 22, Facility_Key = 222, Zone_Name = "2222", Zone_Type = "22222" };
source.Add(curZone);
zoneListBox.DisplayMember = "Facility_Key";
zoneListBox.DataSource = source;
}
public class DimZone
{
public int Zone_Key { get; set; }
public int Zone_ID { get; set; }
public int Facility_Key { get; set; }
public string Zone_Name { get; set; }
public string Zone_Type { get; set; }
}
Try this code and confirm that the changes in zoneListBox.DisplayMember (e.g., "Zone_Key", "Zone_ID", etc.) are immediately reflected in the values being displayed by zoneListBox.
The problem was I was changing zoneListBox.DataSource from one source to another on load, which caused the error. In order for the DataSource to update properly, I had to set zoneListBox.DataSource = null before updating to a new DataSource. I don't know why I have to set it to null first, but it solved my problem. So my updated code is as follows:
private void PopulateUI()
{
if (zoneCollectionAppended != null)
{
zoneListBox.DisplayMember = "Zone_Name";
zoneListBox.ValueMember = "Zone_ID";
//DataSource had to be reset to null before updating to new DataSource
zoneListBox.DataSource = null;
zoneListBox.DataSource = zoneCollectionAppended;
}
}

WPF C#. put observablecollection into List<string>

I have observablecollection which i fill with textboxes on button click event. In my Project is one class where i have list >> public List _RoomNumber = new List(); i want to just send observablecollection value into _RoomNumber list. For example if observablecollection cotains this 4 values : 15, 20, 2323, 3232 i want _RoomNumber context be same so this : 15, 20, 2323, 3232
I hope my question is clear.
This my observablecollection :
ObservableCollection<CheckInData> _CheckInCollection = new ObservableCollection<CheckInData>();
public ObservableCollection<CheckInData> CheckInCollection
{
get { return _CheckInCollection; }
}
public class CheckInData
{
public string RoomNumber { get; set; }
public decimal Price { get; set; }
public string Currecny { get; set; }
public decimal Discount { get; set; }
public string CheckOut { get; set; }
public int TotalDay { get; set; }
public decimal TotalPrice { get; set; }
public int CheckOutYear { get; set; }
public int CheckOutMonth { get; set; }
public int CheckOutDay { get; set; }
public Boolean IncToday { get; set; }
}
this is how im trying to put in list. Problem is that observablecollection contains 102 and 305. _RoomNumber only gets value '1'. please help
private void btnPrintInvoice_Click(object sender, RoutedEventArgs e)
{
//This is Class where my List _RoomNumber is
DataToExcel.Invoice inv = new DataToExcel.Invoice();
foreach (CheckInData coll in CheckInCollection)
{
for (int i = 0; i < _CheckInCollection.Count; i++)
{
inv._RoomNumber.Add(coll.RoomNumber[i].ToString());
}
}
}
You need to make small modification. Try this:
private void btnPrintInvoice_Click(object sender, RoutedEventArgs e)
{
//This is Class where my List _RoomNumber is
DataToExcel.Invoice inv = new DataToExcel.Invoice();
foreach (CheckInData coll in CheckInCollection)
{
inv._RoomNumber.Add(coll.RoomNumber.ToString());
}
}
You don't need to access RoomNumber with index. It is not a collection.
You can use
var roomnumbers = CheckInCollection.Select(x => x.RoomNumber);
inv._RoomNumber = new List(roomnumbers);
Or if you want to reuse the existing List instance,
inv._RoomNumber.Clear();
inv._RoomNumber.AddRange(roomnumbers);
but this seems to be not your case.
Note that in your code, your both inner and outer loops iterate over the same collection :-)
using System.Linq;
...
ObservableCollection<string> ListA = new ObservableCollection<string>();
List<string> ListB = ListA.ToList<string>();

Categories

Resources