Databinding to an ObservableCollection - c#

The following in my code in MainWindow.xaml.cs:
namespace Test
{
public partial class MainWindow : Window
{
public class ChannelInfo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void Notify(string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _channelDescription;
public string ChannelDescription
{
get
{
return _channelDescription;
}
set
{
if (value != _channelDescription)
{
_channelDescription = value;
Notify("ChannelDescription");
}
}
}
}
public ObservableCollection<ChannelInfo> Channels { get; set; }
public MainWindow()
{
InitializeComponent();
Channels = new ObservableCollection<ChannelInfo>()
{
new ChannelInfo() { ChannelDescription = "Ib" }
};
DataContext = Channels;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//((ObservableCollection<ChannelInfo>)DataContext).Add(new ChannelInfo() { ChannelDescription = "Ib" });
}
}
}
In my XAML I have a TextBox defined as follows:
<TextBox Height="23" Text="{Binding ChannelDescription}" HorizontalAlignment="Left" Margin="180,106,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
Now my problem is if I add an item to Channels in the constructor itself, then the TextBox is displaying the bound text. But when I add it in the Window_Loaded like above (uncomment the line), the Text is not displayed.

Related

How to switch between 2 User Controls?

I have been trying to figure out these past 2 days how to switch between 2 User Controls back and forward with buttons inside those User Controls.
I managed to make this happen but with the buttons outside those User Controls.
This is how my project files look
BaseCommand.cs
public class BaseCommand : ICommand
{
private Action<object> _method;
public event EventHandler CanExecuteChanged;
public BaseCommand(Action<object> method)
{
_method = method;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_method.Invoke(parameter);
}
}
MainViewModel.cs
class MainViewModel : INotifyPropertyChanged
{
public ICommand LogInCommand { get; set; }
public ICommand SetupCommand { get; set; }
private object selectedViewModel;
public object SelectedViewModel
{
get { return selectedViewModel; }
set { selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }
}
public MainViewModel()
{
LogInCommand = new BaseCommand(OpenLogIn);
SetupCommand = new BaseCommand(OpenSetup);
}
private void OpenLogIn(object obj)
{
SelectedViewModel = new LogInViewModel();
}
private void OpenSetup(object obj)
{
SelectedViewModel = new SetupViewModel();
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
MainWindow.xaml
<StackPanel>
<ContentControl Content="{Binding SelectedViewModel}"/>
<Button Content="Open LogIn" Height="24" Command="{Binding LogInCommand}"/>
<Button Content="Open Setup" Height="24" Command="{Binding SetupCommand}"/>
</StackPanel>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
LoginViewModel and SetupViewModel are empty classes and their corresponding views have a text block indicating what they are.
What I want is to have instead 2 buttons in my MainWindow.xaml I want 1 in my LogInView.xaml that opens SetupView.xaml and vice versa.
App.xaml
<Application.Resources>
<DataTemplate DataType="{x:Type viewmodels:LogInViewModel}">
<views:LogInView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:SetupViewModel}">
<views:SetupView/>
</DataTemplate>
</Application.Resources>
Move "Open Setup" button to LogInView and "Open LogIn" button to SetupView.
In LogInViewModel create SetupCommand and pass the MainViewModel in the ctor. When the button "Open Setup" is clicked and SetupCommand is invoked then call new OpenSetup method on the MainViewModel.
public class LogInViewModel : INotifyPropertyChanged // etc.
{
private readonly MainViewModel mainViewModel;
public ICommand SetupCommand { get; set; }
public LogInViewModel(MainViewModel mainViewModel)
{
this.mainViewModel = mainViewModel;
SetupCommand = new BaseCommand(OpenSetup);
}
private void OpenSetup(object obj)
{
mainViewModel.OpenSetup();
}
....
}
Similar for SetupViewModel
public class SetupViewModel : INotifyPropertyChanged // etc.
{
private readonly MainViewModel mainViewModel;
public ICommand LogInCommand { get; set; }
public SetupViewModel(MainViewModel mainViewModel)
{
this.mainViewModel = mainViewModel;
LogInCommand = new BaseCommand(OpenLogIn);
}
private void OpenLogIn(object obj)
{
mainViewModel.OpenLogIn();
}
....
}
Finally, remove commands from MainViewModel, modify OpenLogIn and OpenSetup methods and pass reference to the MainViewModel when you create new instance of LogInViewModel or SetupViewModel.
public class MainViewModel : INotifyPropertyChanged
{
private object selectedViewModel;
public object SelectedViewModel
{
get { return selectedViewModel; }
set { selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }
}
public MainViewModel()
{
OpenLogIn();
}
public void OpenLogIn()
{
SelectedViewModel = new LogInViewModel(this);
}
public void OpenSetup()
{
SelectedViewModel = new SetupViewModel(this);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}

Deleting and Editing an item in a listview with Viewmodel and without using the codebehind

In the shown code i need to know the coding to be replaced in place of question mark in the code. I need to delete,edit and update the item in the list view without writing any code in code behind. I only want to do these operations by bindin view with view model through Icommand
This a class in my model Playlist.cs
namespace MvvmDemo.Models
{
public class Playlist
{
public string Title { get; set; }
}
}
This is a class in my viewmodel PlaylistsViewModel.cs
namespace MvvmDemo.ViewModels
{
public class PlaylistsViewModel
{
public ObservableCollection Playlists { get; private set; } = new ObservableCollection();
public ICommand AddPlaylistCommand { get; private set; }
public ICommand DeletePlaylistCommand { get; private set; }
public ICommand EditPlaylistCommand { get; private set; }
public PlaylistsViewModel()
{
AddPlaylistCommand = new Command(AddPlaylist);
DeletePlaylistCommand = new Command(DeletePlaylist);
}
public void AddPlaylist()
{
var newPlaylist = "Playlist " + (Playlists.Count + 1);
Playlists.Add(new Playlist { Title = newPlaylist });
}
public void DeletePlaylist()
{
????????????????
}
public void EditPlaylist()
{
????????????????
}
}
}
you have to make the command is parameterised and pass binding data through the parameter.
and from that data you can get the index value of selected.using that remove the item from the list.
Playlists.RemoveAt("INDEX_NUMBER");
To update it in the view use "INotifyProperty" also
If you want to delete and edit item in ListView, firstly, you should need to use ICommand, then you could need to use INotifyPropertyChanged to implement Inotify.
I do one sample that you can take a look. Choosing one Item and long press with the left mouse button, you will see two ways, delete Item and Edit Item action.
<ContentPage.Content>
<StackLayout>
<ListView
x:Name="mylistview"
ItemsSource="{Binding lists}"
SelectedItem="{Binding selecteditem}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem
Command="{Binding BindingContext.DeletePlaylistCommand, Source={x:Reference Name=mylistview}}"
IsDestructive="true"
Text="Delete Item" />
<MenuItem
Command="{Binding BindingContext.EditPlaylistCommand, Source={x:Reference Name=mylistview}}"
IsDestructive="true"
Text="Edit Item" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label Text="{Binding Title}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Page19 : ContentPage, INotifyPropertyChanged
{
public ObservableCollection<Playlist> lists { get; set; }
//public RelayCommand1 AddPlaylistCommand { get; set; }
public RelayCommand DeletePlaylistCommand { get; set; }
public RelayCommand EditPlaylistCommand { get; set; }
private Playlist _selecteditem;
public Playlist selecteditem
{
get { return _selecteditem; }
set
{
_selecteditem = value;
RaisePropertyChanged("selecteditem");
}
}
public Page19 ()
{
InitializeComponent ();
lists = new ObservableCollection<Playlist>()
{
new Playlist(){Id=1,Title="list 1"},
new Playlist(){Id=2, Title="list 2"},
new Playlist(){Id=3,Title="list 3"},
new Playlist(){Id=4,Title="list 4"},
new Playlist(){Id=5,Title="list 5"},
new Playlist(){Id=6,Title="list 6"},
};
DeletePlaylistCommand = new RelayCommand(DeletePlaylist);
EditPlaylistCommand = new RelayCommand(EditPlaylist);
selecteditem = lists[0];
this.BindingContext = this;
}
public void AddPlaylist()
{
}
public void DeletePlaylist()
{
Playlist item = selecteditem;
lists.Remove(item);
}
public void EditPlaylist()
{
Playlist item = selecteditem;
int id = item.Id;
foreach(Playlist playl in lists.Where(a=>a.Id==id))
{
playl.Title = "chenge title";
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class Playlist: INotifyPropertyChanged
{
private int _Id;
public int Id
{
get { return _Id; }
set
{
_Id = value;
RaisePropertyChanged("Id");
}
}
private string _Title;
public string Title
{
get { return _Title;}
set
{
_Title = value;
RaisePropertyChanged("Title");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here is the RelayCommd:
public class RelayCommand : ICommand
{
readonly Action _execute;
public RelayCommand(Action execute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_execute();
}
}
You can use observablecollection. It will reflect add,remove operation of item to the listview. And for editing item you have to raise property changed for all property you are editing.To simplify that property changed you can implement property changed event to your Playlist model class.
Like
public void DeletePlaylist()
{
Playlists.Remove(newPlaylist);
}
public void EditPlaylist()
{
newPlaylist.Title="Refreshed Playlist"
}
public class Playlist:INotifyPropertyChanged
{
private string title;
public string Title
{
get{return title;}
set{title=value;
NotifyPropertyChanged();}
}
}

"Cascade" binding on ObservableCollection, containing other ObservableCollection

I have a project where I need to display a list of contract (Class Affaire).
Each contract has a list of phases (Class Phase).
I display each of them in 2 different ListView using binding.
Problem is when I remove a Phase from ListView, nor the ListView where are displayed Phases, nor my ObjectCollection are updated.
I created a context with two distinct ObservableCollection :
ObservableCollection, where is the list of Affaire.
ObservableCollection that are list of phases present in selected Affaire
My context is made as follow :
public class Contexte : INotifyPropertyChanged
{
private Affaire selectedAffaire;
private Phase selectedPhase;
private Assemblage selectedAssemblage;
public Affaire SelectedAffaire
{
get { return selectedAffaire; }
set
{
selectedAffaire = value;
this.NotifyPropertyChanged("SelectedAffaire");
}
}
public Phase SelectedPhase
{
get { return selectedPhase; }
set
{
selectedPhase = value;
this.NotifyPropertyChanged("SelectedPhase");
}
}
public Assemblage SelectedAssemblage
{
get { return selectedAssemblage; }
set
{
selectedAssemblage = value;
this.NotifyPropertyChanged("SelectedAssemblage");
}
}
private ObservableCollection<Affaire> listeDesAffaires;
public ObservableCollection<Affaire> ListeDesAffaires
{
get { return listeDesAffaires; }
set { NotifyPropertyChanged(ref listeDesAffaires, value); }
}
/**************************************************/
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string nomPropriete)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(nomPropriete));
}
private bool NotifyPropertyChanged<T>(ref T variable, T valeur, [CallerMemberName] string nomPropriete = null)
{
if (object.Equals(variable, valeur)) return false;
variable = valeur;
NotifyPropertyChanged(nomPropriete);
return true;
}
}
My Class Affaire :
public class Affaire : INotifyPropertyChanged
{
public long ID { get; set; }
private string nom;
public string Nom
{
get { return this.nom; }
set
{
if (this.nom != value)
{
this.nom = value;
this.NotifyPropertyChanged("Nom");
}
}
}
private string code;
public string Code
{
get { return this.code; }
set
{
if (this.code != value)
{
this.code = value;
this.NotifyPropertyChanged("Code");
}
}
}
private string comm;
public string Comm
{
get { return this.comm; }
set
{
if (this.comm != value)
{
this.comm = value;
this.NotifyPropertyChanged("Comm");
}
}
}
private ObservableCollection<Phase> listPhases;
public ObservableCollection<Phase> ListPhases {
get { return listPhases; }
set
{
listPhases = value;
if (PropertyChanged != null)
{
NotifyPropertyChanged("ListPhases");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
....
}
My class Phase :
public class Phase : INotifyPropertyChanged
{
private string nomPhase;
public string NomPhase
{
get { return this.nomPhase; }
set
{
if (this.nomPhase != value)
{
this.nomPhase = value;
this.NotifyPropertyChanged("NomPhase");
}
}
}
private int priorite;
public int Priorite
{
get { return this.priorite; }
set
{
if (this.priorite != value)
{
this.priorite = value;
this.NotifyPropertyChanged("Priorite");
}
}
}
private string commPhase;
public string CommPhase
{
get { return this.commPhase; }
set
{
if (this.commPhase != value)
{
this.commPhase = value;
this.NotifyPropertyChanged("CommPhase");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public long IdAffaire { get; set; }
public long ID { get; set; }
private ObservableCollection<Assemblage> listAssemblages;
public ObservableCollection<Assemblage> ListAssemblages
{
get { return listAssemblages; }
set
{
listAssemblages = value;
if (PropertyChanged != null)
{
NotifyPropertyChanged("ListAssemblages");
}
}
}
...
}
1) When I doubleclick on a contract(in ListView1), I display in ListView2 list of its phases, I do the following :
contexte.SelectedAffaire = (Affaire)ListView1.SelectedItem;
contexte.SelectedAffaire.getListPhases();
afficherListview("2");
2) When I edit my Phase, all is updated correctly in my view, and also in my ObservableCollection
3) For adding/removing a new Phase, all is solved.
Edit :
Example given by Netstep works perfectly but I still meet an issue :
I have a third level "Assembly", this is an ObservableCollection in class "Phase", I have no problem to navigate with the four ListViews, but I meet a problem when I want to make something else : When I right-click on the header of "Phase", I want to display in the list of Assembly, the list of all assemblies contained in Affaire, without filtering on Phase.
For this I do the following : I am on the 3rd level listview Assemblies, I make right click on Phase header and event is as following :
Phase ph = new Phase();
ph.IdAffaire = contexte.SelectedAffaire.ID;
ph.ListAssemblages = new ObservableCollection<Assemblage>(contexte.SelectedAffaire.getListAssemblages(true));
contexte.SelectedPhase = ph;
I "shit" a bit making a new empty phase, just to put an ObservableCollection inside and bind the ObservableCollection to my ListView3.
Edit : That part of code works good... I just refreshed the context somewhere in my code and forgot about it, sure that there was something wrong in biding... All solved thanks
Here is the example, based on your source, that will handle all stuff.
a View Models:
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace WpfApp2
{
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string nomPropriete)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(nomPropriete));
}
}
public class Contexte : BaseViewModel
{
private Affaire _selectedAffaire;
private Phase _selectedPhase;
public ObservableCollection<Affaire> ListeDesAffaires { get; set; }
public Affaire SelectedAffaire
{
get { return _selectedAffaire; }
set
{
_selectedAffaire = value;
this.NotifyPropertyChanged("SelectedAffaire");
}
}
public Phase SelectedPhase
{
get { return _selectedPhase; }
set
{
_selectedPhase = value;
this.NotifyPropertyChanged("SelectedPhase");
}
}
public Contexte()
{
ListeDesAffaires = new ObservableCollection<Affaire>
{
new Affaire("Affaire1"),
new Affaire("Affaire2")
};
}
}
public class Affaire : BaseViewModel
{
private string nom;
public string Nom
{
get { return this.nom; }
set
{
this.nom = value;
this.NotifyPropertyChanged("Nom");
}
}
public ObservableCollection<Phase> ListPhases { get; set; }
public Affaire(string n)
{
nom = n;
ListPhases = new ObservableCollection<Phase>
{
new Phase { NomPhase = nom + "_Phase1" },
new Phase { NomPhase = nom + "_Phase2" }
};
}
}
public class Phase : BaseViewModel
{
private string nomPhase;
public string NomPhase
{
get { return this.nomPhase; }
set
{
this.nomPhase = value;
this.NotifyPropertyChanged("NomPhase");
}
}
public ObservableCollection<Assemblage> ListAssemblages { get; set; }
}
public class Assemblage : BaseViewModel
{
private string nom;
public string Nom
{
get { return this.nom; }
set
{
this.nom = value;
this.NotifyPropertyChanged("Nom");
}
}
}
}
a MainWindow.xaml:
<Window x:Class="WpfApp2.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:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:Contexte x:Name="Contexte" d:IsDataSource="True" />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding ListeDesAffaires}" DisplayMemberPath="Nom" SelectedItem="{Binding SelectedAffaire}"/>
<ListBox Grid.Column="1" ItemsSource="{Binding SelectedAffaire.ListPhases}" DisplayMemberPath="NomPhase" />
<Button Grid.Column="2" VerticalAlignment="Top" Click="FillClick">Fill</Button>
<ListBox Grid.Column="2" ItemsSource="{Binding SelectedPhase.ListAssemblages}" DisplayMemberPath="Nom" Margin="0,20,0,0"/>
</Grid>
</Window>
And some code from your question (MainWindow.xaml.cs):
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApp2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void FillClick(object sender, RoutedEventArgs e)
{
Phase ph = new Phase();
ph.NomPhase = "SomeId";
ph.ListAssemblages = new ObservableCollection<Assemblage>()
{
new Assemblage { Nom = "Assemblage1" },
new Assemblage { Nom = "Assemblage2" }
};
Contexte.SelectedPhase = ph;
}
}
}
And here is the result:
This is basic sample that you can extend. It handles all field modification and Add/Remove objects and displays on screen. There is no additional code in MainWindow.xaml.cs. Please ask questions, if any.

Binding TextBox to object WPF

I'm trying to make the TextBox show the stringBody property of the CurrentDialog property of the window. Here's the XAML part:
<TextBox x:Name="ComposerBox" Height="90.302" Margin="311,0,141.355,10"
...
Text="{Binding Body}"
ScrollViewer.CanContentScroll="True" SpellCheck.IsEnabled="True"
VerticalAlignment="Bottom">
Here is a string from the windows constructor:
MessagingBox.DataContext = CurrentDialog;
I've also tried to set DataContext to this with no result.
Here's how CurrentDialog is defined:
private MessageDialog CurrentDialog { get; set; }
Here's the MessageDialog class definition:
[Serializable][DataContract]
public class MessageDialog
{
public string Name { get; private set; }
public UserData User { get; private set; }
private List<Message> Dialog = new List<Message>();
public string Body { get; private set; }
public MessageDialog(UserData data)
{
Name = data.Username;
User = data;
Body = "";
}
public void Add(Message msg)
{
Dialog.Add(msg);
Body += $"{msg.From}: {msg.Body} \n\n";
}
}
}
The binding doesn't work at all. I also want it to be one-way.
Text="{Binding CurrentPerson.Body}"
Not sure why the binding path contains CurrentPerson, when it should be CurrentDialog, but even that isn't supposed to be there. Since the DataContext is already set to CurrentDialog, you can simply bind the text to :
Text="{Binding Body}"
You need to implement INotifyPropertyChanged, so the WPF know when the property changed:
[Serializable][DataContract]
public class MessageDialog : INotifyPropertyChanged
{
#region public string Body
private string m_Body;
public string Body
{
get { return m_Body; }
private set
{
if (m_Body == value)
return;
m_Body = value;
this.NotifyPropertyChanged();
}
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}

Binding a nested object to a DataGrid in c# WPF

I am trying to bind the data displayed in a DataGrid to a dynamic list of object (WhisperModel) which is inside another object(WhisperReader). The DataGrid only displays the headers, but no values. How can I make the DataGrid dynamically update itself when the list "whispers" is changed?
Main Window XAML:
<DataGrid x:Name="whisperDataGrid" Margin="10,69,10,10" IsReadOnly="True" ItemsSource="{Binding}"/>
Main Window C#
public partial class MainWindow : Window
{
private WhisperReader wr;
public MainWindow()
{
InitializeComponent();
wr = new WhisperReader();
whisperDataGrid.DataContext = wr.whispers;
}
WhisperReader:
class WhisperReader
{
public ObservableCollection<WhisperModel> whispers { get; private set; }
public WhisperReader()
{
whispers = new ObservableCollection<WhisperModel>();
}
WhisperModel:
class WhisperModel
{
public DateTime sentTime { get; set; }
public string sender { get; set; }
public string message { get; set; }
}
I think your problem is that it doesn't know when to update itself because:
You have made the whispers list the data context.
The properties that you are binding to don't use INotifyPropertyChanged.
WhisperReader and WhisperModel are not public
All bindings must be public, must be properties, and must call the PropertyChanged method.
The PropertyChanged function triggers the binding updates.
Try this...
public partial class MainWindow : Window
{
private WhisperReader wr;
public MainWindow()
{
InitializeComponent();
wr = new WhisperReader();
whisperDataGrid.DataContext = wr;
}
public class WhisperReader : INotifyPropertyChanged
{
ObservableCollection<WhisperModel> _whispers;
public ObservableCollection<WhisperModel> whispers
{
get { return _whispers; }
private set
{
_whispers = value;
NotifyPropertyChanged();
}
}
public WhisperReader()
{
whispers = new ObservableCollection<WhisperModel>();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class WhisperModel : INotifyPropertyChanged
{
public DateTime sentTime { get; set; }
private string _sender;
public string sender
{
get { return _sender; }
set { _sender = value; NotifyPropertyChanged();
}
private string _message;
public string message
{
get { return _message; }
set { _message = value; NotifyPropertyChanged();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
<DataGrid x:Name="whisperDataGrid" Margin="10,69,10,10" IsReadOnly="True" AutoGenerateColumns="True" ItemsSource="{Binding whispers}"/>

Categories

Resources