WPF C# DataGrid单单元格内嵌列表展示员工访客及功能实现问题
WPF DataGrid 单元格列表展示开发问题
使用的技术和工具
- Visual Studio 2019
- WPF
- C#
需求说明
- 在DataGrid的「员工」列单个单元格中展示1名或多名员工列表,需同时支持单员工和多员工两种场景的实现方式;
- 在「访客」列单个单元格中展示1名或多名访客列表;
- 最后一列仅展示1条关联对应员工和访客的描述信息,无需每行重复展示;
- 访客信息旁需添加编辑和删除按钮,支持修改访客详情或从列表中移除访客,操作结果同步更新到模拟数据库或正式数据库中。
遇到的问题
- 目前仅能绑定预约列表,尝试获取并绑定下层属性时绑定失效;
- 所有员工都被拆分到独立行展示,不符合单单元格内存放员工列表的需求;
- 访客列表也存在相同问题,需将多条访客信息存放在同一DataGrid单元格中;
- 展开DataGrid项后无法正常滚动,需解决该异常。
现有代码
XAML代码 [AppointmentsWindow.xaml]
<DataGrid x:Name="DataGridAppointments" ItemsSource="{Binding Appointments}" AutoGenerateColumns="False" SelectionMode="Single" CanUserAddRows="false" CanUserDeleteRows="False" SelectionUnit="FullRow"> <!-- DataGrid columns --> <DataGrid.Columns> <DataGridTextColumn Header="Title" Binding="{Binding Title}" /> <DataGridTextColumn Header="Date and Time" Binding="{Binding StartDateTime}" /> <DataGridTextColumn Header="Location" Binding="{Binding Location}" /> </DataGrid.Columns> <!-- DataGrid Expander (i.e. expanding/collapsing row items) --> <DataGrid.RowHeaderTemplate> <DataTemplate> <Expander Expanded="ExecuteExpanderToggler" Collapsed="ExecuteExpanderToggler"/> </DataTemplate> </DataGrid.RowHeaderTemplate> <!--Inner DataGrid for additional information --> <DataGrid.RowDetailsTemplate> <DataTemplate> <DataGrid ItemsSource="{Binding Appointments}" AutoGenerateColumns="False" SelectionMode="Single" CanUserAddRows="false" CanUserDeleteRows="False" SelectionUnit="FullRow"> <DataGrid.Columns> <DataGridTextColumn Header="Employee" Binding="{Binding Appointments.Organizer}"/> <DataGridTemplateColumn Header="Visitors"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <DataGrid ItemsSource="{Binding Appointments.Visitors}"> <DataGrid.Columns> <DataGridTextColumn Header="Visitor name" Binding="{Binding FirstName}" /> <DataGridTextColumn Header="License plate" Binding="{Binding LicensePlate}" /> <DataGridTextColumn Header="Attendees" Binding="{Binding Appointments.Attendees}" /> </DataGrid.Columns> </DataGrid> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTextColumn Header="Description" Binding="{Binding Appointments.Description}"/> </DataGrid.Columns> </DataGrid> </DataTemplate> </DataGrid.RowDetailsTemplate> </DataGrid>
C#后端代码 [AppointmentsWindow.xaml.cs]
public AppointmentViewModel AppointmentViewModel { get; set; } = new AppointmentViewModel(); public AppointmentsWindow() { InitializeComponent(); WindowStartupLocation = WindowStartupLocation.CenterScreen; //TEST DataContext = AppointmentViewModel; }
C#后端代码 [AppointmentViewModel.cs]
public class AppointmentViewModel { public IList<Appointment> Appointments { get; set; } public AppointmentViewModel() { Appointments = new List<Appointment>(); Organizer employee = new Organizer(1, "test1@live.nl", "0612345671", "Name1", "lastName1"); Visitor vis1 = new Visitor(1, "visitor1@live.nl", "0612345671", "Visitor1", "LastName1", "5-ABC-1"); Visitor vis2 = new Visitor(2, "visitor2@live.nl", "0612345672", "Visitor2", "LastName2", "5-ABC-2"); IList<Visitor> visitors = new List<Visitor> { vis1, vis2 }; Appointment app1 = new Appointment(1, "Title1", "location1", "description1", new DateTime(2015, 1, 10), new DateTime(), employee, visitors, 5); Appointment app2 = new Appointment(1, "Title2", "location2", "description2", new DateTime(2015, 2, 15), new DateTime(), employee, visitors, 10); Appointment app3 = new Appointment(1, "Title3", "location3", "description3", new DateTime(2015, 3, 20), new DateTime(), employee, visitors, 35); Appointments.Add(app1); Appointments.Add(app2); Appointments.Add(app3); } }
C#后端代码 [PropertyNotifier.cs]
public class PropertyNotifier : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyRaised(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } }
C#后端代码 [Appointment.cs]
public class Appointment : PropertyNotifier { private int id; public int Id { get { return id; } set { id = value; OnPropertyRaised(nameof(Id)); } } private string title; public string Title { get { return title; } set { title = value; OnPropertyRaised(nameof(Title)); } } private string location; public string Location { get { return location; } set { location = value; OnPropertyRaised(nameof(Location)); } } private string description; public string Description { get { return description; } set { description = value; OnPropertyRaised(nameof(Description)); } } private DateTime? startDateTime; public DateTime? StartDateTime { get { return startDateTime; } set { startDateTime = value; OnPropertyRaised(nameof(StartDateTime)); } } private DateTime? endDateTime; public DateTime? EndDateTime { get { return endDateTime; } set { endDateTime = value; OnPropertyRaised(nameof(EndDateTime)); } } private Organizer organizer; public Organizer Organizer { get { return organizer; } set { organizer = value; OnPropertyRaised(nameof(Organizer)); } } private IList<Visitor> visitors; public IList<Visitor> Visitors { get { return visitors; } set { visitors = value; OnPropertyRaised(nameof(Visitors)); } } private int attendees; public int Attendees { get { return attendees; } set { attendees = value; OnPropertyRaised(nameof(Attendees)); } } public Appointment(int id, string title, string location, string description, DateTime? startDateTime, DateTime? endDateTime, Organizer organizer, IList<Visitor> visitors, int attendees) { Id = id; Title = title; Location = location; Description = description; StartDateTime = startDateTime; EndDateTime = endDateTime; Organizer = organizer; Visitors = visitors; Attendees = attendees; } }
C#后端代码 [Person.cs]
public abstract class Person : PropertyNotifier { private int id; public int Id { get { return id; } set { id = value; OnPropertyRaised(nameof(Id)); } } private string email; public string Email { get { return email; } set { email = value; OnPropertyRaised(nameof(Email)); } } private string phone; public string Phone { get { return phone; } set { phone = value; OnPropertyRaised(nameof(Phone)); } } private string firstName; public string FirstName { get { return firstName; } set { firstName = value; OnPropertyRaised(nameof(FirstName)); } } private string lastName; public string LastName { get { return lastName; } set { lastName = value; OnPropertyRaised(nameof(LastName)); } } protected Person() { } protected Person(int id, string email, string phone, string firstName, string lastName) { Id = id; Email = email; Phone = phone; FirstName = firstName; LastName = lastName; } }
C#后端代码 [Organizer.cs]
public class Organizer : Person { public Organizer(int id, string email, string phone, string firstName, string lastName) : base(id, email, phone, firstName, lastName) { } }
C#后端代码 [Visitor.cs]
public class Visitor : Person { private string licensePlate; public string LicensePlate { get { return licensePlate; } private set { licensePlate = value; OnPropertyRaised(nameof(LicensePlate)); } } public Visitor(int id, string email, string phone, string firstName, string lastName, string licensePlate) : base(id, email, phone, firstName, lastName) { LicensePlate = licensePlate; } }
内容的提问来源于stack exchange,提问作者user16906859
相关产品推荐
相关产品推荐

