更新另一个集合中的集合成员的属性以显示在DataGrid中

问题描述 投票:0回答:1

当我更改数据网格显示中更新的集合中的集合成员的属性时,我该怎么做呢?

在我的例子中,我有一个ObservableCollection的Employees。每个员工都有一个List属性。当我将员工的汽车价值分配给新的列表时,它将成功更新。当我分配Employee的Car的Model属性时,它不会更新。

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));
        }

    }
}
wpf data-binding inotifycollectionchanged
1个回答
0
投票

我稍微修改了你的代码,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));
        }
    }

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.