Person.cs
using System.ComponentModel;
namespace MyWPFProject
{
public class Person : INotifyPropertyChanged
{
public string Name
{
get
{
return name;
}
set
{
name = value;
OnPropertyChanged(nameof(Name));
}
}
public string Surname
{
get
{
return surname;
}
set
{
surname = value;
OnPropertyChanged(nameof(Surname));
}
}
public int Age
{
get
{
return age;
}
set
{
age = value;
OnPropertyChanged(nameof(Age));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
private string name;
private string surname;
private int age;
}
}
RelayCommand.cs
using System;
using System.Windows.Input;
namespace MyWPFProject
{
public class RelayCommand : ICommand
{
private readonly Func<bool> _canExecute;
private readonly Action _execute;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
}
}
MainWindow.xaml
<Window x:Class="MyWPFProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyWPFProject"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<ListView Name="listView" ItemsSource="{Binding Path=ListOfPeople, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}"/>
<GridViewColumn Header="Surname" DisplayMemberBinding="{Binding Path=Surname}"/>
<GridViewColumn Header="Age" DisplayMemberBinding="{Binding Path=Age}"/>
</GridView>
</ListView.View>
</ListView>
<Button FontSize="20" MinHeight="30" Margin="180,20,180,0" Content="Zmień" Command="{Binding ChangeData}"/>
<Button FontSize="20" MinHeight="30" Margin="180,20,180,0" Content="Dodaj osobę" Command="{Binding AddPersonWindowOpen}"/>
</StackPanel>
</Grid>
</Window>
AddPersonWindow.xaml
<Window x:Class="MyWPFProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyWPFProject"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<ListView Name="listView" ItemsSource="{Binding Path=ListOfPeople, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}"/>
<GridViewColumn Header="Surname" DisplayMemberBinding="{Binding Path=Surname}"/>
<GridViewColumn Header="Age" DisplayMemberBinding="{Binding Path=Age}"/>
</GridView>
</ListView.View>
</ListView>
<Button FontSize="20" MinHeight="30" Margin="180,20,180,0" Content="Zmień" Command="{Binding ChangeData}"/>
<Button FontSize="20" MinHeight="30" Margin="180,20,180,0" Content="Dodaj osobę" Command="{Binding AddPersonWindowOpen}"/>
</StackPanel>
</Grid>
</Window>
W MainWindow.xaml.cs i AddWindow.xaml.cs nic nie mam poza InitializeComponents()
I najważniejsze czyli ViewModel
ViewModel.cs
using System.ComponentModel;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.Windows;
namespace MyWPFProject
{
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
ListOfPeople = new ObservableCollection<Person>();
ListOfPeople.Add(new Person() { Name = "Michael", Surname = "Jordan", Age = 22 });
ListOfPeople.Add(new Person() { Name = "Jan", Surname = "Kowalski", Age = 21 });
ListOfPeople.Add(new Person() { Name = "Anna", Surname = "Nowak", Age = 20 });
}
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!=null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private void ChangeDataExecute()
{
ListOfPeople[1].Name = "Marek";
ListOfPeople[1].Surname = "Adamiak";
ListOfPeople[1].Age = 24;
//Tutaj natomiast jakbym to odkomentowal to po wcisnieciu buttona zmien wszystko dziala, tzn View tez sie aktualizuje
//ListOfPeople.Add(new Person() { Name = "Jan" });
}
private void AddPersonWindowOpenExecute()
{
AddPersonWindow addPersonWindow = new AddPersonWindow();
addPersonWindow.Show();
}
private void AddPersonToListExecute()
{
foreach(Window window in Application.Current.Windows)
{
if (window.GetType() == typeof(AddPersonWindow))
{
//I tu lezy problem. Sprawdzalem debuggerem ze element jest prawidlowo dodawany do listy, ale nie View w MainWindow nie jest odswiezany
ListOfPeople.Add(new Person()
{
Name = (window as AddPersonWindow).nameTextBox.Text,
Surname=(window as AddPersonWindow).surnameTextBox.Text,
Age = int.Parse((window as AddPersonWindow).ageTextbox.Text)
});
(window as AddPersonWindow).Close();
}
}
}
public ICommand ChangeData { get { return new RelayCommand(ChangeDataExecute); } }
public ICommand AddPersonWindowOpen { get { return new RelayCommand(AddPersonWindowOpenExecute); } }
public ICommand AddPersonToList { get { return new RelayCommand(AddPersonToListExecute); } }
public ObservableCollection<Person> ListOfPeople
{
get
{
return listOfPeople;
}
set
{
listOfPeople = value;
OnPropertyChanged("ListOfPeople");
}
}
private ObservableCollection<Person> listOfPeople;
public event PropertyChangedEventHandler PropertyChanged;
}
}
Mam tu prostą aplikację w WPF, która obsługuje 2 okna.
Jak wciskam button DodajOsobe to otwiera sie nowe okno
Mogę teraz wpisać nową osobę. Jak to zrobię to chcę, żeby ona była dodana do listy i tak się dzieje, bo sprawdzałem debuggerem że w ViewModelu wlasciwość ListOfPeople się aktualizuje (ma teraz 4 elementy), ale nie aktualizuje mi się to w View w głównym oknie. Natomiast jak w funkcji ChangeDataExecute dodam tam element do listy to wszystko działa, tzn. View się aktualizuje. Dlaczego tak się dzieje?