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);
}
}
CodePudding user response:
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"
/>