WPF wiązanie danych, execute i update property

0

Cześć.

Zaczynam dopiero naukę WPF i eksperymentuje trochę z różnymi kontrolkami.

W przykładzie poniżej chciałbym pobrać dane z "formularza" (imię, nazwisko oraz stanowisko) i po naciśnięciu przycisku umieścić je w DataGrid - źródło danych dla DataGrid zbindowane jest do listy obiektów typu Person (property Persons). Z pobraniem danych z formularza nie mam problemu. Klasa SaveDataCommand obsługuje pobieranie danych z formularza (dla testów wyświetlam dane w MessageBox). Nie bardzo wiem jak zmodyfikować tą klasę tak, aby w metodzie Execute dodać do listy Persons obiekt person i w ten sposób zaktualizować dane w DataGrid. Próbowałem do konstruktora klasy SaveDataCommand przekazać property Persons przez referencję, ale niestety dane nie aktualizują się. Zakładam, że w ogóle mam błędne założenia co do sposobu obsługi tego co chcę uzyskać dlatego chciałbym Was prosić o wskazówki. W skrócie : w jaki sposób po naciśnięciu przycisku mogę dodać dane z formularza do DataGrid?

<Grid>
        <TextBlock HorizontalAlignment="Left" Margin="10,22,0,0" TextWrapping="Wrap" Text="Imię:" VerticalAlignment="Top"/>
        <TextBlock HorizontalAlignment="Left" Margin="10,45,0,0" TextWrapping="Wrap" Text="Nazwisko:" VerticalAlignment="Top"/>
        <TextBlock HorizontalAlignment="Left" Margin="10,71,0,0" TextWrapping="Wrap" Text="Stanowisko:" VerticalAlignment="Top"/>
        <TextBox x:Name="txtBoxFirstName" HorizontalAlignment="Left" Height="23" Margin="80,12,0,0" TextWrapping="Wrap"  Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120" />
        <TextBox x:Name="txtBoxSecondName" HorizontalAlignment="Left" Height="23" Margin="80,35,0,0" TextWrapping="Wrap" Text="{Binding Path=SecondName, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
        <ComboBox x:Name="combOccupation" HorizontalAlignment="Left" Margin="80,63,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Path=Occupations}" DisplayMemberPath="Name" Text="{Binding Path=OccupationData}"/>
        <Button x:Name="btnTestCommand" Content="Test values" HorizontalAlignment="Left" Margin="10,101,0,0" VerticalAlignment="Top" Width="75" Command="{Binding Path=SaveData}"/>
        <DataGrid HorizontalAlignment="Left" Margin="10,144,0,0" VerticalAlignment="Top" Height="137" Width="497" ItemsSource="{Binding Path=Persons}"/>
    </Grid>

Oto kod mojego przykładu :

public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private Person person;

        private List<Person> persons;

        private List<Occupation> occupations;

        private SaveDataCommand saveData;

        public SaveDataCommand SaveData
        {
            get
            {
                if (saveData == null)
                    saveData = new SaveDataCommand(this.person);

                return saveData;
            }
        }

        
        public string FirstName
        {
            get
            {
                return person.FirstName;
            }
            set
            {
                if (person.FirstName != value)
                {
                    person.FirstName = value;

                    OnPropertyChanged("FirstName");
                }
            }
        }


        public string SecondName
        {
            get
            {
                return person.SecondName;
            }
            set
            {
                if (person.SecondName != value)
                {
                    person.SecondName = value;

                    OnPropertyChanged("SecondName");
                }
            }
        }


        public string OccupationData
        {
            get
            {
                return person.OccupationData;
            }
            set
            {
                if(person.OccupationData != value)
                { 
                    person.OccupationData = value;

                    OnPropertyChanged("OccupationData");
                }
            }
        }

        public List<Occupation> Occupations
        {
            get
            {
                return occupations;
            }
            set
            {
                occupations = value;
            }
        }

        public List<Person> Persons
        {
            get
            {
                return persons;
            }
            set
            {
                persons = value;
            }
        }

        public ViewModel()
        {
            person = new Person();

            persons = new List<Person>();

            occupations = new List<Occupation>();
            occupations.Add(new Occupation() { Name = "Student" });
            occupations.Add(new Occupation() { Name = "Doktorant" });
            occupations.Add(new Occupation() { Name = "Doktor" });
            occupations.Add(new Occupation() { Name = "Profesor" });
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
    }


    public class SaveDataCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;

        private Person person;

        public SaveDataCommand(Person person)
        {
            this.person = person;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            MessageBox.Show(string.Format("{0} - {1} - {2}", person.FirstName, person.SecondName, person.OccupationData));
        }
    }

    public class Occupation
    {
        public string Name { get; set; }
    }

    public class Person
    {
        public string FirstName { get; set; }

        public string SecondName { get; set; }

        public string OccupationData { get; set; }
    }
0

Update.

Chyba udało mi się rozwiązać problem. Prosiłbym tylko o informację czy zrobiłem to zgodnie z zasadami C# & WPF.

Oto co zmieniłem:

1. Lista obiektów klasy Person została utworzona za pomocą typu kolekcji ObservableCollection

 
public ObservableCollection<Person> Persons { get; set; }

2. Do konstruktora klasy SaveDataCommand odpowiedzialnej za wykonanie akcji przycisku przekazałem obiekt klasy ViewModel

 
public SaveDataCommand SaveData
        {
            get
            {
                if (saveData == null)
                    saveData = new SaveDataCommand(this);

                return saveData;
            }
        }

3. W metodzie Execute klasy SaveDataCommand mogę już dodać element do listy Persons

 
public void Execute(object parameter)
{
    this.viewModel.Persons.Add(new Person() { FirstName = viewModel.FirstName, SecondName = viewModel.SecondName, OccupationData = viewModel.OccupationData });
}

Poniżej całość:

    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private Person person;

        private List<Occupation> occupations;

        private SaveDataCommand saveData;

        public SaveDataCommand SaveData
        {
            get
            {
                if (saveData == null)
                    saveData = new SaveDataCommand(this);

                return saveData;
            }
        }

        
        public string FirstName
        {
            get
            {
                return person.FirstName;
            }
            set
            {
                if (person.FirstName != value)
                {
                    person.FirstName = value;

                    OnPropertyChanged("FirstName");
                }
   
            }
        }


        public string SecondName
        {
            get
            {
                return person.SecondName;
            }
            set
            {
                if (person.SecondName != value)
                {
                    person.SecondName = value;

                    OnPropertyChanged("SecondName");
                }
         
            }
        }


        public string OccupationData
        {
            get
            {
                return person.OccupationData;
            }
            set
            {
                if (person.OccupationData != value)
                {
                    person.OccupationData = value;

                    OnPropertyChanged("OccupationData");
                }

            }
        }

        public List<Occupation> Occupations
        {
            get
            {
                return occupations;
            }
            set
            {
                occupations = value;
            }
        }

        public ObservableCollection<Person> Persons { get; set; }


        public ViewModel()
        {
            person = new Person();

            occupations = new List<Occupation>();
            occupations.Add(new Occupation() { Name = "Student" });
            occupations.Add(new Occupation() { Name = "Doktorant" });
            occupations.Add(new Occupation() { Name = "Doktor" });
            occupations.Add(new Occupation() { Name = "Profesor" });


            Persons = new ObservableCollection<Person>();

        }

        private void OnPropertyChanged(string propertyName)
        {
            
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            
        }
        
    }


    public class SaveDataCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;

        private ViewModel viewModel;


        public SaveDataCommand(ViewModel viewModel)
        {
            this.viewModel = viewModel;
            this.viewModel.PropertyChanged += new PropertyChangedEventHandler(data_PropertyChanged);
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            //MessageBox.Show(string.Format("{0} - {1} - {2}", viewModel.FirstName, viewModel.SecondName, viewModel.OccupationData));

            this.viewModel.Persons.Add(new Person() { FirstName = viewModel.FirstName, SecondName = viewModel.SecondName, OccupationData = viewModel.OccupationData });
        }

        private void data_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }
    }

    public class Occupation
    {
        public string Name { get; set; }
    }

    public class Person
    {
        public string FirstName { get; set; }

        public string SecondName { get; set; }

        public string OccupationData { get; set; }
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1