Question about ListView binding with MVVM - c#

I'm working on an app that has a ListView requiring a column with a checkbox. Below is an example of the XAML. IsSelected is part of the Items class, but I'm receiving the error "Cannot resolve property 'IsSelected' in data context of type 'App.ViewModel.ItemViewModel'". I do not receive any errors at runtime, but the XAML shows an error because it is looking for an IsSelected property in the ItemViewModel. If I add DataContext="{Binding Items}" I am no longer able to bind SelectedValue to SelectedItem.
Any thoughts on what I'm doing wrong or how I can restructure this in order to get it working?
<Window x:Class="App.View.AppWindow"
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:App.View"
xmlns:vm="clr-namespace:App.ViewModel"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:ui="http://schemas.modernwpf.com/2019"
mc:Ignorable="d"
Title="AppWindow" Height="800" Width="1100"
ResizeMode="CanMinimize>
<Grid DataContext="{StaticResource ItemViewModel}">
<ListView ItemsSource="{Binding Items}"
SelectedValue="{Binding SelectedItem}">
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="Selected" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding ItemNumber}"
Header="Item #"
Width="80"/>
<GridViewColumn DisplayMemberBinding="{Binding TransactionCode}"
Header="Detail"
Width="200"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
Here is the declaration of Items in the ItemViewModel:
using App.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
namespace App.ViewModel;
public class ItemViewModel : INotifyPropertyChanged
{
// Property for items
private ObservableCollection<Item>? _items;
public ObservableCollection<Item>? Items
{
get => _items;
set
{
_items = value;
OnPropertyChanged(nameof(Items));
}
}
// Property for selected item
private Item? _selectedItem;
public Item? SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem));
}
}
// Constructor Item ViewModel
public ItemViewModel()
{
Items = new ObservableCollection<Item>();
}
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Here is the model for Item in the Model:
namespace App.Models;
public class Item
{
public bool IsSelected { get; set; }
public string? ItemNumber { get; set; }
public string? Detail { get; set; }
}

Related

WPF ListView SelectedItem Not Updating With Expander in DataTemplate

I'm creating a WPF application using C# and MVVM, and I'm having some trouble with the SelectedItem of a ListView.
In the contrived example, the scenario: I have a PersonViewModel containing a List of Person objects. Each person object has its own List of Address objects. My goal is to load all of the Person objects into a ListView. Additionally, the ListView DataTemplate should include Expanders that show the available addresses for each person.
The problem: This all actually works decently enough. The only problem is that if a user selects the expander for a person object, it doesn't actually change the SelectedItem property of the ListView (which is bound to a SelectedPerson object in the view model).
I'm relatively confident that the code works otherwise because if I click on the ListView row (outside the boundaries of the contained expander), the SelectedPerson property is updated. Is there anyway to somehow bind when the expander is clicked to the SelectedPerson property? (I'm also open to other UI ideas that will get my information across in a cleaner, more easily implemented manner).
Person.cs
using System.Collections.Generic;
namespace ListViewExpanderTest
{
public class Person
{
public Person()
{
Addresses = new List<Address>();
}
public string Name { get; set; }
public List<Address> Addresses { get; set; }
}
}
Address.cs
namespace ListViewExpanderTest
{
public class Address
{
public int HouseNumber { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
}
}
PersonViewModel.cs
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ListViewExpanderTest
{
public class PersonViewModel : INotifyPropertyChanged
{
private Person _selectedPerson;
private Address _selectedAddress;
public List<Person> People { get; set; }
public Person SelectedPerson
{
get
{
return _selectedPerson;
}
set
{
_selectedPerson = value;
OnPropertyChanged();
}
}
public Address SelectedAddress
{
get
{
return _selectedAddress;
}
set
{
_selectedAddress = value;
OnPropertyChanged();
}
}
public PersonViewModel()
{
People = new List<Person>
{
new Person
{
Name = "Person 1",
Addresses = new List<Address>
{
new Address {HouseNumber = 1, StreetName = "Fake St", City = "Fake City" },
new Address {HouseNumber = 2, StreetName = "Super Fake St", City = "Super Fake City" }
}
},
new Person
{
Name = "Person 2",
Addresses = new List<Address>
{
new Address {HouseNumber = 10, StreetName = "Fake St", City = "Fake City" },
new Address {HouseNumber = 20, StreetName = "Super Fake St", City = "Super Fake City" }
}
}
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainWindow.xaml
<Window x:Class="ListViewExpanderTest.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:ListViewExpanderTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:PersonViewModel />
</Window.DataContext>
<Grid>
<ListView ItemsSource="{Binding People, Mode=TwoWay}"
SelectedItem="{Binding SelectedPerson}">
<ListView.ItemTemplate>
<DataTemplate>
<Expander >
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Expander.Header>
<Expander.Content>
<ListView ItemsSource="{Binding Addresses, Mode=TwoWay}"
SelectedItem="{Binding SelectedAddress}">
<ListView.View>
<GridView>
<GridViewColumn Width="50" Header="Number" DisplayMemberBinding="{Binding HouseNumber}" />
<GridViewColumn Width="100" Header="Street" DisplayMemberBinding="{Binding StreetName}" />
<GridViewColumn Width="100" Header="City" DisplayMemberBinding="{Binding City}" />
</GridView>
</ListView.View>
</ListView>
</Expander.Content>
</Expander>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
As your view model contains a single SelectedPerson property it doesn't make sense to me to include an expander in the datatemplate. If you can change your UI, the below example seems to make more sense to me. You can obviously place the address 'panel' anywhere you like.
Also, have you tried selecting an address from the sub listview? Does the binding work?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding People, Mode=TwoWay}"
SelectedItem="{Binding SelectedPerson}"
DisplayMemberPath="Name">
</ListView>
<ListView Grid.Column="1"
ItemsSource="{Binding SelectedPerson.Addresses, Mode=TwoWay}"
SelectedItem="{Binding SelectedAddress}">
<ListView.View>
<GridView>
<GridViewColumn Width="50" Header="Number" DisplayMemberBinding="{Binding HouseNumber}" />
<GridViewColumn Width="100" Header="Street" DisplayMemberBinding="{Binding StreetName}" />
<GridViewColumn Width="100" Header="City" DisplayMemberBinding="{Binding City}" />
</GridView>
</ListView.View>
</ListView>
</Grid>

How to get a reference of a ListView item to its datatemplates ViewModel which is created as static resource? [duplicate]

I did my research that people tend to use ViewModel to achieve this but I am sort of stuck in it.
I have a
public ObservableCollection<Order> orderList { get; set; } = new ObservableCollection<Order>();
in MainWindow which is already filled up with data.
in MainWindow XAML I have a User Control inside the TabControl:
<TabControl x:Name="TabCollection">
<TabItem Header="UC1">
<local:UserControl1/>
</TabItem>
<TabItem Header="UC2">
<local:UserControl2/>
</TabItem>
</TabControl>
We only talk about UC1 here so in UC1 XAML here I have a ListView inside:
<UserControl.DataContext>
<local:UserControl1VM/>
</UserControl.DataContext>
<ListView x:Name="ListViewText">
<ListView.View>
<GridView>
<GridViewColumn Header="First name" DisplayMemberBinding="{Binding Firstname}"/>
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding Lastname}"/>
<GridViewColumn Header="Order" DisplayMemberBinding="{Binding Ordername}"/>
<GridViewColumn Header="Delivery time" DisplayMemberBinding="{Binding Deliverytime}"/>
<GridViewColumn Header="Phone Number" DisplayMemberBinding="{Binding Phone}"/>
<GridViewColumn Header="Address" DisplayMemberBinding="{Binding Address}"/>
<GridViewColumn Header="Email" DisplayMemberBinding="{Binding Email}"/>
</GridView>
</ListView.View>
</ListView>
And here's the code in UserControl1VM.cs:
namespace QuickShop
{
class UserControl1VM : INotifyPropertyChanged
{
private ObservableCollection<Order> orderList;
public ObservableCollection<Order> OrderList
{
get { return orderList; }
set
{
orderList = value;
PropertyChanged(this, new PropertyChangedEventArgs("OrderList"));
}
}
//
private void FindDeliveryOrders(IEnumerable<Order> sortList)
{
foreach (var order in sortList)
{
if (order.Delivery.Equals("Yes"))
{
//deliveryOrders.Add(order);
this.ListViewText.Items.Add(new Order { Firstname = order.Firstname, Lastname = order.Lastname, Ordername = order.Ordername, Deliverytime = order.Deliverytime, Phone = order.Phone, Address = order.Address, Email = order.Email });
}
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
}
And Of course these are incomplete codes because I don't know how to proceed next.
My goal is just to populate the ListView and it will automatically update itself if orderList changes. But right now I couldn't even know whether the ViewModel is working or not, any thoughts and code demo would be very grateful.
A UserControl should never have a "private" view model, as you assign it to the DataContext in the UserControl's XAML. It should instead expose dependency properties that could be bound to properties of an externally provided view model object.
Declare an ItemsSource property like this:
public partial class UserControl1 : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register(
nameof(ItemsSource), typeof(IEnumerable), typeof(UserControl1));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public UserControl1()
{
InitializeComponent();
}
}
And bind the ListView like this:
<UserControl ...>
...
<ListView ItemsSource="{Binding ItemsSource,
RelativeSource={RelativeSource AncestorType=UserControl}}">
...
</ListView>
...
</UserControl>
When you use the UserControl, bind the property to a view model property:
<TabItem Header="UC1">
<local:UserControl1 ItemsSource="{Binding OrderList}"/>
</TabItem>
The last XAML snippet assumes that the object in the UserControl's DataContext has a OrderList property. This would automatically happen when the TabControl is bound to a collection of view model objects with that property.
Alternatively, let the elements in the UserControl's XAML directly bind to the properties of the object in the inherited DataContext.
<UserControl ...>
...
<ListView ItemsSource="{Binding OrderList}">
...
</ListView>
...
</UserControl>
Your control would not have to expose additional bindable properties, but it would only work with DataContext objects that actually provide the expected source properties.

C#, WPF, bind List<string> to DataGrid

I have trouble to bind a List to a DataGrid. It should be as simple as possible. I'm new to WPF and this is for my personal education.
I have a View(Editor),ViewModel(VMText) and a Data(JustText) class.
My source so far:
JustText.cs
namespace Model
{
public class Text
{
private string _code;
public string Code
{
get { return _code; }
set { _code = value; }
}
public Text()
{
_code = "Hello World!\nHow you doin'?";
}
}
}
VMText.cs
namespace ViewModel
{
public class VMText
{
private Model.Text _code;
public List<string> Code
{
get { return new List<string>(_code.Code.Split('\n')); }
set { _code.Code = System.String.Join("\n", value.ToArray()); }
}
private View.Editor editor;
public VMText(View.Editor editor)
{
_code = new Model.Text();
this.editor = editor;
}
}
}
Editor.xaml
<Window x:Class="View.Editor"
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:View"
mc:Ignorable="d"
Title="Editor" Height="240.024" Width="269.895">
<Grid Background="#FF292929" Margin="0,0,-6.8,0.4">
<DataGrid x:Name="dataGrid"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top"
Width="200pt"
Height="100pt"
DataContext="{Binding vmText}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Code, UpdateSourceTrigger=PropertyChanged}" Foreground="Black" Width="60" Header="Test" IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Editor.xaml.cs
namespace View
{
public partial class Editor : Window
{
private ViewModel.VMText vmText;
#region Constructor
public Editor()
{
InitializeComponent();
vmText = new ViewModel.VMText(this);
DataContext = vmText;
}
#endregion
}
}
I just want to show List which is created in VMText in one column in the DataGrid
I guess you simply want to display the strings in the Code source collection property of the view model in the DataGrid.
You should then bind the ItemsSource property of the DataGrid to the Code source property of the view model and then bind the DataGridTextColumn to the strings in the Code list itself. You just have to modify the XAML markup of your view a bit to be able to see the strings. Try this:
<DataGrid x:Name="dataGrid"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top"
Width="200pt"
Height="100pt"
ItemsSource="{Binding Code}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding}"
Foreground="Black" Width="60" Header="Test" IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>
You should implement INotifyPropertyChanged to notify binding that property changed. Also for the collections look at ObservableCollection instead of List.
Bind VMText.Code to DataGrid ItemSource. You don't need to Inicialize DataGrid DataContract in View when you do it in code behind.
ViewModel
namespace ViewModel
{
public class VMText : INotifyPropertyChanged
{
public VMText(View.Editor editor)
{
_code = new Model.Text();
this.editor = editor;
}
public List<string> Code
{
get
{
return new List<string>(_code.Code.Split('\n'));
}
set
{
_code.Code = System.String.Join("\n", value.ToArray());
NotifyPropertyChanged("Code");
}
}
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private Model.Text _code;
private View.Editor editor;
}
}
View
<Window x:Class="View.Editor"
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:View"
mc:Ignorable="d"
Title="Editor" Height="240.024" Width="269.895">
<Grid Background="#FF292929" Margin="0,0,-6.8,0.4">
<DataGrid x:Name="dataGrid"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top"
Width="200pt"
Height="100pt"
ItemsSource="{Binding Code}>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Code"
Foreground="Black" Width="60"
Header="Test"
IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>
</Grid>

How to get the currently selected ListView object item back to the ViewModel on a button click

The title pretty much sums it up. I've been trying to use the button's CommandParameter but I'm not sure what it should be and what additional code I need in my ViewModel class. Any help would be appreciated.
XAML:
<ItemsControl>
<StackPanel Orientation="Horizontal">
<Button Command="{Binding ButtonClick}" Width="150" Margin="5" Height="22" HorizontalAlignment="Left">Click</Button>
</StackPanel>
<ListView Name="listView" Grid.Row="1" BorderThickness="0" ItemsSource="{Binding myObjects}">
<ListView.View>
<GridView>
<GridViewColumn Header="Space ID" DisplayMemberBinding="{Binding ID}" Width="Auto" />
</GridView>
</ListView.View>
</ListView>
</ItemsControl>
ViewModel C#:
public ICommand ButtonClick
{
get { return new DelegateCommand(BtnClick); }
}
private void BtnClick()
{
//Access selected object of type myObject here.
}
DelegateCommand class:
public class DelegateCommand : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action)
{
_action = action;
}
public void Execute(object parameter)
{
_action();
}
public bool CanExecute(object parameter)
{
return true;
}
}
You can bind the ListView's SelectedItem to a property of your viewmodel. Like the way you bind 'myObjects' with the ItemsSource.
I solved this by making a couple of changes. Firstly, my Delegate ICommand class could not support this behavior, so I modified it to the one listed here. Then I updated my XAML and ViewModel.
Updated XAML:
<StackPanel Orientation="Horizontal">
<Button Command="{Binding Command1}" CommandParameter="{Binding ElementName=listView}" Width="150" Margin="5" Height="22" HorizontalAlignment="Left">Button1</Button>
</StackPanel>
<ListView Name="listView" ItemsSource="{Binding myObjects}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}" Width="Auto" />
</GridView>
</ListView.View>
</ListView>
Updated ViewModel:
public ICommand Command1 { get; set; }
public MainWindowViewModel()
{
this.Command1 = new DelegateCommand(ExecuteCommand1, CanExecuteCommand1);
}
public bool CanExecuteCommand1(object parameter)
{
return true;
}
private void ExecuteCommand1(object parameter)
{
ListView listView = parameter as ListView;
foreach (MyObject myObject in listView.SelectedItems)
{
// Do stuff.
}
}

Binding items into ListBox multiple columns

I am trying to add my data into multiple columns ListBox, I did it but I am facing a hard problem when trying to retrieve the Data from the list box. is there a way to put an object instead of text into a listBox row?
<ListView Name="listBox1" ItemsSource="{Binding Items}" Margin="28,28,68,67" FlowDirection="RightToLeft" MouseDoubleClick="listBox1_MouseDoubleClick">
<ListView Name="listBox1" ItemsSource="{Binding Items}" Margin="28,28,68,67" FlowDirection="RightToLeft" MouseDoubleClick="listBox1_MouseDoubleClick">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="a" Width="100" DisplayMemberBinding="{Binding Path=ID}" />
<GridViewColumn Header="b" Width="100" DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Header="c" Width="100" DisplayMemberBinding="{Binding Path=F}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Grid>
and this is the code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public sealed class MyListBoxItem
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Students st = new Students(1, "name","anything");
listBox1.ItemsSource = new List(new[] { st });
}
private void listBox1_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
object ob = listBox1.SelectedItem;
string i = ((MyListBoxItem)listBox1.SelectedItem).Field1;
}
}
and here is the class Students
class Students
{
int id;
string name;
string f;
public Students(int id, string name,string f)
{
this.id = id;
this.name = name;
this.f = f;
}
public int ID
{
get { return id; }
set { id = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public string F
{
get { return f; }
set { f = value; }
}
}
Don't use listBox1.Items.Add(....). Rather use listBox1.ItemsSource = new List(new[] {st});
Then change Your DisplayMemberBindings to "Id", "Name" respectively.
There is no need for the ListBoxItem Class.
== EDIT ==
You were very close to getting it perfectly. I've attached below how it should work. The important things to notice are the Bindings in the ListView for ItemsSource and SelctedITem, and setting IsSynchronisedWithCurrentItem to true.
Also, in the bottom two rows ofthe grid, I've shown two different ways of binding to the selected item, one using "/" notation, and the other using a property on the ViewModel
XAML
<Window x:Class="StackOverflow11087468.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView Name="listBox1"
Grid.Row="0"
ItemsSource="{Binding Students}"
SelectedItem="{Binding SelectedStudent}"
IsSynchronizedWithCurrentItem="True"
Margin="28,28,68,67"
FlowDirection="RightToLeft">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="a"
Width="100"
DisplayMemberBinding="{Binding Path=ID}" />
<GridViewColumn Header="b"
Width="100"
DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Header="c"
Width="100"
DisplayMemberBinding="{Binding Path=F}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock>ID</TextBlock>
<TextBox Text="{Binding Students/ID}" />
</StackPanel>
<StackPanel Grid.Row="2"
Orientation="Horizontal">
<TextBlock>ID</TextBlock>
<TextBox Text="{Binding SelectedStudent.ID}" />
</StackPanel>
</Grid>
</Window>
Main.Window.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace StackOverflow11087468
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
}
ViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace StackOverflow11087468
{
public class ViewModel : INotifyPropertyChanged
{
public ObservableCollection<Student> Students { get; set; }
public ViewModel()
{
this.Students = new ObservableCollection<Student>();
Students.Add(new Student(98760987, "Student1", "F"));
Students.Add(new Student(98760988, "Student22", "M"));
}
public Student SelectedStudent
{
get { return _selectedStudent; }
set
{
_selectedStudent = value;
RaisePropertyChanged("SelectedStudent");
}
}
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
private Student _selectedStudent;
}
}

Categories