更新另一个集合中集合成员的 属性 以显示在 DataGrid 中
Updating a collection member's property within another collection to show in a DataGrid
当我更改集合中某个集合成员的 属性 时,我该如何做到这一点,它会在数据网格显示中更新?
在我的示例中,我有一个 Employees 的 ObservableCollection。每个员工都有一个列表 属性。
当我将员工的汽车值分配给新列表时,它将成功更新。当我分配员工的汽车模型 属性 时,它不会更新。
MainWindow.xaml
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="DataBindings.MainWindow" Title="MainWindow" Height="332" Width="474" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<CollectionViewSource x:Key="GridDataSource" Source="{Binding Employees}" />
</Window.Resources>
<Grid Margin="0,0,0,-1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DataGrid Grid.Row="1" ItemsSource="{Binding Source={StaticResource GridDataSource}}" AutoGenerateColumns="False" CanUserAddRows="False" Margin="0,0,0,114">
<DataGrid.Columns>
<DataGridTextColumn x:Name="Names" Width="Auto" Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn x:Name="Cars" Width="Auto" Header="Cars" Binding="{Binding CarsString}" />
</DataGrid.Columns>
</DataGrid>
<Button Content="Update" Click="Update" HorizontalAlignment="Left" Margin="170,202,0,-20" Grid.Row="1" VerticalAlignment="Top" Width="75" />
</Grid>
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows;
namespace DataBindings
{
public partial class MainWindow : Window
{
DAL dataAccess = new DAL();
public MainWindow()
{
InitializeComponent();
}
public ObservableCollection<Employee> Employees { get { return dataAccess.EmployeesList; } }
private void Update(object sender, RoutedEventArgs e)
{
Employees[1].Name = "Mike"; //changing the name property on the collection of employees works
Debug.WriteLine($"Mike's Car is a {Employees[1].Cars[0].Model}");
Employees[1].Cars[0].Model = "Volvo"; //changing the model of car in a cars list does not
Debug.WriteLine($"Mike's Car is a {Employees[1].Cars[0].Model}");
}
}
}
DAL.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace DataBindings
{
public class DAL : ObservableCollection<Employee>
{
public ObservableCollection<Employee> EmployeesList = new ObservableCollection<Employee>();
public DAL()
{
List<Car> carList = new List<Car>();
carList.Add(new Car { Model = "Ford" });
carList.Add(new Car { Model = "Honda" });
EmployeesList.Add(new Employee { Name = "Bob", Cars = carList });
EmployeesList.Add(new Employee { Name = "John", Cars = carList });
//EmployeesList.CollectionChanged += EmployeesList_CollectionChanged;
}
}
public class Employee : INotifyPropertyChanged
{
private string empName;
public List<Car> empCars = new List<Car>();
private string carsString;
public string Name
{
get { return this.empName; }
set
{
if (this.empName != value)
{
empName = value;
this.NotifyPropertyChanged("Name");
};
}
}
public List<Car> Cars
{
get { return this.empCars; }
set
{
if (this.empCars != value)
{
empCars = value;
carsToString(empCars);
this.NotifyPropertyChanged("Cars");
};
}
}
public string CarsString
{
get { return this.carsString; }
set
{
if (this.carsString != value)
{
carsString = value;
this.NotifyPropertyChanged("CarsString");
};
}
}
public void carsToString(List<Car> Cars)
{
string carString = "";
foreach (Car car in Cars)
{
carString += car.Model + " ";
}
CarsString = carString;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public class Car : INotifyPropertyChanged
{
private string carModel;
public string Model
{
get { return this.carModel; }
set
{
if (this.carModel != value)
{
carModel = value;
this.NotifyPropertyChanged("Model");
};
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
我稍微修改了你的代码,IMO 可以进一步改进。
这是我的 xaml:
<Window.DataContext>
<local:DAL />
</Window.DataContext>
<Grid Margin="0,0,0,-1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DataGrid x:Name="grid" Grid.Row="1" ItemsSource="{Binding EmployeesList}" AutoGenerateColumns="False" CanUserAddRows="False" Margin="0,0,0,114">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Names">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Cars">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CarsString, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Content="Update" Click="Update" HorizontalAlignment="Left" Margin="170,202,0,-20" Grid.Row="1" VerticalAlignment="Top" Width="75" />
</Grid>
这是我的隐藏代码:
您可以为您的 UpdateButton 使用 ICommand,这样您就可以将代码留在干净的地方:https://www.c-sharpcorner.com/UploadFile/e06010/wpf-icommand-in-mvvm/
public DAL VM => (DAL) DataContext;
public MainWindow()
{
InitializeComponent();
}
private void Update(object sender, RoutedEventArgs e)
{
VM.EmployeesList[1].Name = "Mike"; //changing the name property on the collection of employees works
Debug.WriteLine($"Mike's Car is a {VM.EmployeesList[1].Cars[0].Model}");
VM.EmployeesList[1].Cars[0].Model = "Volvo"; //changing the model of car in a cars list does not
Debug.WriteLine($"Mike's Car is a {VM.EmployeesList[1].Cars[0].Model}");
}
这是我的 DAL.cs
请注意,我将您的 List 更改为 ObservableCollection 然后在访问器中,您需要确保 CarsString 已更新,因为您没有直接在视图中更新它。
public class DAL : INotifyPropertyChanged
{
private ObservableCollection<Employee> _employeesList;
public ObservableCollection<Employee> EmployeesList
{
get => _employeesList;
set
{
_employeesList = value;
OnPropertyChanged();
}
}
public DAL()
{
EmployeesList = new ObservableCollection<Employee>();
ObservableCollection<Car> carList = new ObservableCollection<Car>();
carList.Add(new Car { Model = "Ford" });
carList.Add(new Car { Model = "Honda" });
EmployeesList.Add(new Employee { Name = "Bob", Cars = carList });
EmployeesList.Add(new Employee { Name = "John", Cars = carList });
//EmployeesList.CollectionChanged += EmployeesList_CollectionChanged;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Employee : INotifyPropertyChanged
{
private string empName;
public ObservableCollection<Car> empCars = new ObservableCollection<Car>();
private string carsString;
public string Name
{
get { return this.empName; }
set
{
if (this.empName != value)
{
empName = value;
this.NotifyPropertyChanged("Name");
};
}
}
public ObservableCollection<Car> Cars
{
get
{
carsToString(empCars);
this.NotifyPropertyChanged("CarsString");
return this.empCars;
}
set
{
if (this.empCars != value)
{
empCars = value;
carsToString(empCars);
this.NotifyPropertyChanged("Cars");
this.NotifyPropertyChanged("CarsString");
};
}
}
public string CarsString
{
get { return this.carsString; }
set
{
if (this.carsString != value)
{
carsString = value;
this.NotifyPropertyChanged("CarsString");
};
}
}
public void carsToString(ObservableCollection<Car> Cars)
{
string carString = "";
foreach (Car car in Cars)
{
carString += car.Model + " ";
}
CarsString = carString;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public class Car : INotifyPropertyChanged
{
private string carModel;
public string Model
{
get { return this.carModel; }
set
{
if (this.carModel != value)
{
carModel = value;
this.NotifyPropertyChanged("Model");
};
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
当我更改集合中某个集合成员的 属性 时,我该如何做到这一点,它会在数据网格显示中更新?
在我的示例中,我有一个 Employees 的 ObservableCollection。每个员工都有一个列表 属性。 当我将员工的汽车值分配给新列表时,它将成功更新。当我分配员工的汽车模型 属性 时,它不会更新。
MainWindow.xaml
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="DataBindings.MainWindow" Title="MainWindow" Height="332" Width="474" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<CollectionViewSource x:Key="GridDataSource" Source="{Binding Employees}" />
</Window.Resources>
<Grid Margin="0,0,0,-1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DataGrid Grid.Row="1" ItemsSource="{Binding Source={StaticResource GridDataSource}}" AutoGenerateColumns="False" CanUserAddRows="False" Margin="0,0,0,114">
<DataGrid.Columns>
<DataGridTextColumn x:Name="Names" Width="Auto" Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn x:Name="Cars" Width="Auto" Header="Cars" Binding="{Binding CarsString}" />
</DataGrid.Columns>
</DataGrid>
<Button Content="Update" Click="Update" HorizontalAlignment="Left" Margin="170,202,0,-20" Grid.Row="1" VerticalAlignment="Top" Width="75" />
</Grid>
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows;
namespace DataBindings
{
public partial class MainWindow : Window
{
DAL dataAccess = new DAL();
public MainWindow()
{
InitializeComponent();
}
public ObservableCollection<Employee> Employees { get { return dataAccess.EmployeesList; } }
private void Update(object sender, RoutedEventArgs e)
{
Employees[1].Name = "Mike"; //changing the name property on the collection of employees works
Debug.WriteLine($"Mike's Car is a {Employees[1].Cars[0].Model}");
Employees[1].Cars[0].Model = "Volvo"; //changing the model of car in a cars list does not
Debug.WriteLine($"Mike's Car is a {Employees[1].Cars[0].Model}");
}
}
}
DAL.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace DataBindings
{
public class DAL : ObservableCollection<Employee>
{
public ObservableCollection<Employee> EmployeesList = new ObservableCollection<Employee>();
public DAL()
{
List<Car> carList = new List<Car>();
carList.Add(new Car { Model = "Ford" });
carList.Add(new Car { Model = "Honda" });
EmployeesList.Add(new Employee { Name = "Bob", Cars = carList });
EmployeesList.Add(new Employee { Name = "John", Cars = carList });
//EmployeesList.CollectionChanged += EmployeesList_CollectionChanged;
}
}
public class Employee : INotifyPropertyChanged
{
private string empName;
public List<Car> empCars = new List<Car>();
private string carsString;
public string Name
{
get { return this.empName; }
set
{
if (this.empName != value)
{
empName = value;
this.NotifyPropertyChanged("Name");
};
}
}
public List<Car> Cars
{
get { return this.empCars; }
set
{
if (this.empCars != value)
{
empCars = value;
carsToString(empCars);
this.NotifyPropertyChanged("Cars");
};
}
}
public string CarsString
{
get { return this.carsString; }
set
{
if (this.carsString != value)
{
carsString = value;
this.NotifyPropertyChanged("CarsString");
};
}
}
public void carsToString(List<Car> Cars)
{
string carString = "";
foreach (Car car in Cars)
{
carString += car.Model + " ";
}
CarsString = carString;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public class Car : INotifyPropertyChanged
{
private string carModel;
public string Model
{
get { return this.carModel; }
set
{
if (this.carModel != value)
{
carModel = value;
this.NotifyPropertyChanged("Model");
};
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
我稍微修改了你的代码,IMO 可以进一步改进。
这是我的 xaml:
<Window.DataContext>
<local:DAL />
</Window.DataContext>
<Grid Margin="0,0,0,-1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DataGrid x:Name="grid" Grid.Row="1" ItemsSource="{Binding EmployeesList}" AutoGenerateColumns="False" CanUserAddRows="False" Margin="0,0,0,114">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Names">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Cars">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CarsString, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Content="Update" Click="Update" HorizontalAlignment="Left" Margin="170,202,0,-20" Grid.Row="1" VerticalAlignment="Top" Width="75" />
</Grid>
这是我的隐藏代码: 您可以为您的 UpdateButton 使用 ICommand,这样您就可以将代码留在干净的地方:https://www.c-sharpcorner.com/UploadFile/e06010/wpf-icommand-in-mvvm/
public DAL VM => (DAL) DataContext;
public MainWindow()
{
InitializeComponent();
}
private void Update(object sender, RoutedEventArgs e)
{
VM.EmployeesList[1].Name = "Mike"; //changing the name property on the collection of employees works
Debug.WriteLine($"Mike's Car is a {VM.EmployeesList[1].Cars[0].Model}");
VM.EmployeesList[1].Cars[0].Model = "Volvo"; //changing the model of car in a cars list does not
Debug.WriteLine($"Mike's Car is a {VM.EmployeesList[1].Cars[0].Model}");
}
这是我的 DAL.cs 请注意,我将您的 List 更改为 ObservableCollection 然后在访问器中,您需要确保 CarsString 已更新,因为您没有直接在视图中更新它。
public class DAL : INotifyPropertyChanged
{
private ObservableCollection<Employee> _employeesList;
public ObservableCollection<Employee> EmployeesList
{
get => _employeesList;
set
{
_employeesList = value;
OnPropertyChanged();
}
}
public DAL()
{
EmployeesList = new ObservableCollection<Employee>();
ObservableCollection<Car> carList = new ObservableCollection<Car>();
carList.Add(new Car { Model = "Ford" });
carList.Add(new Car { Model = "Honda" });
EmployeesList.Add(new Employee { Name = "Bob", Cars = carList });
EmployeesList.Add(new Employee { Name = "John", Cars = carList });
//EmployeesList.CollectionChanged += EmployeesList_CollectionChanged;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Employee : INotifyPropertyChanged
{
private string empName;
public ObservableCollection<Car> empCars = new ObservableCollection<Car>();
private string carsString;
public string Name
{
get { return this.empName; }
set
{
if (this.empName != value)
{
empName = value;
this.NotifyPropertyChanged("Name");
};
}
}
public ObservableCollection<Car> Cars
{
get
{
carsToString(empCars);
this.NotifyPropertyChanged("CarsString");
return this.empCars;
}
set
{
if (this.empCars != value)
{
empCars = value;
carsToString(empCars);
this.NotifyPropertyChanged("Cars");
this.NotifyPropertyChanged("CarsString");
};
}
}
public string CarsString
{
get { return this.carsString; }
set
{
if (this.carsString != value)
{
carsString = value;
this.NotifyPropertyChanged("CarsString");
};
}
}
public void carsToString(ObservableCollection<Car> Cars)
{
string carString = "";
foreach (Car car in Cars)
{
carString += car.Model + " ";
}
CarsString = carString;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public class Car : INotifyPropertyChanged
{
private string carModel;
public string Model
{
get { return this.carModel; }
set
{
if (this.carModel != value)
{
carModel = value;
this.NotifyPropertyChanged("Model");
};
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}