Reputation: 3
Quite a newbie in the world of WPF. I've been hurting my eyes for several days now, looking for a solution, but didn't manage to make it right.
What I'm trying to achieve :
Seems quite simple, uh ? I manage to do it all in the MainWindow.xaml.cs (only using ObservableCollection, no 'PropertyChanged' yet), but I can't make it work in the ViewModel.
Now my code :
Client.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataBindingTestInViewModel
{
class Client
{
protected string _firstName;
protected string _name;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
}
}
MainWindow.xaml
<Window x:Class="DataBindingTestInViewModel.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:DataBindingTestInViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" ItemsSource="{Binding Clients}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Label Grid.Column="0" Content="{Binding FirstName}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Grid.Row="1" Click="Button_Click">Add a client</Button>
</Grid>
</Window>
MainWindow.xaml.cs (create an instance of ViewModel + Button_Click event)
using System.Windows;
namespace DataBindingTestInViewModel
{
/// <summary>
/// Logique d'interaction pour MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ViewModel viewmodel = new ViewModel();
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
viewmodel.AddClient();
}
}
}
ViewModel.cs
using System.Collections.ObjectModel;
using System.Windows;
namespace DataBindingTestInViewModel
{
class ViewModel
{
private ObservableCollection<Client> _clients = new ObservableCollection<Client>();
public ViewModel()
{
_clients.Add(new Client() { FirstName = "John", Name = "Doe" });
_clients.Add(new Client() { FirstName = "Jane", Name = "Doe" });
//MessageBox.Show("Constructeur du View Model appelé.");
}
public ObservableCollection<Client> Clients
{
get { return _clients; }
}
public void AddClient()
{
_clients.Add( new Client() { FirstName = "Donald", Name = "Trump" } );
MessageBox.Show("First element : " + _clients[0].FirstName + "\n" +
"Third element : " + _clients[2].FirstName );
}
}
}
Results :
What I think happens :
The MainWindow data context is binded to the ViewModel's Client instance. I create and add element in a new instance called in MainWindow - and that's not the one used in the datacontext.
Questions :
I guess that'll be a piece of cake for y'all. Thank you !!
Upvotes: 0
Views: 373
Reputation: 35656
you are correct about working with 2 instances (one created in xaml and another in code-behind). there 2 ways to fix the situation.
work with the instance created in xaml. to get reference to that instance cast DataContext to vm type:
public partial class MainWindow : Window
{
ViewModel viewmodel;
public MainWindow()
{
InitializeComponent();
viewModel = (ViewModel)DataContext;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
viewmodel.AddClient();
}
}
work with the instance created in code. set DataContext from code too:
public partial class MainWindow : Window
{
ViewModel viewmodel = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = viewmodel;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
viewmodel.AddClient();
}
}
and remove xaml part:
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
Upvotes: 1