Why ComboBox Loded a Different Value In WPF MVVM? - c#

I have an Employee Class That Contains two Property Id and Name.I was trying To show them in ComboBox and made a click event To show the Selected Item Through message box. The Click Event Is Working fine it shows me the correct value but in combobox it shows me the diffrent value. I am a newb in WPF MVVM. This is my EmployeeModelView Class
class EmployeeViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public ObservableCollection<Employee> Employee
{
get
{
return employee;
}
set
{
employee = value;
}
}
private ObservableCollection<Employee> employee = new ObservableCollection<Employee>
{
new Employee {Id=1,Name="asdasd"},
new Employee { Id=2,Name="wwerewr"}
};
private Employee selectedEmployee;
public Employee SelectedEmployee
{
get
{
return selectedEmployee;
}
set
{
selectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
}
}
This is my View
<Grid>
<ComboBox x:Name="cmbEmployee"
ItemsSource="{Binding Employee}"
SelectedItem="{Binding SelectedEmployee}"
HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Center" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
I get this Output
This is my main Window Code
EmployeeViewModel emps;
public MainWindow()
{
InitializeComponent();
emps = new EmployeeViewModel();
this.DataContext = emps;
}
private void button_Click(object sender, RoutedEventArgs e)
{
Employee emp = emps.SelectedEmployee;
MessageBox.Show(emp.Id + " " + emp.Name);
}

You have to set ComboBox ItemTemplate:
<ComboBox x:Name="cmbEmployee"
ItemsSource="{Binding Employee}"
SelectedItem="{Binding SelectedEmployee}"
HorizontalAlignment="Left" VerticalAlignment="Top" Width="120">
<ComboBox.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Id}"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</WrapPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Solution 1:
Have you tried to use DisplayMemberPath attribute to your ComboBox?
<ComboBox x:Name="cmbEmployee"
ItemsSource="{Binding Employee}"
SelectedItem="{Binding SelectedEmployee}"
DisplayMemberPath="Name"
HorizontalAlignment="Left" VerticalAlignment="Top" Width="120">
It shows the Name of the Employee in the Combo.
Solution 2:
It's better to override ToString of Employee
public class Employee{
public override string ToString(){
return $"{Id} {Name}";
}
}
Like this, your combo will show the text as you want. And it make more clair in button_Click
private void button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(emps.SelectedEmployee?.ToString());
}

Related

WPF Using TabItem and binding ViewModels

My goal is have each TabItem linked to a specific viewmodel. Furthermore, after transvering through each TabItem, the user input should not be reset. I am finding solutions for this and came across a potential solution but my testing failed me.
I have searched for answers and chose to do the following as it seems it applies the MVVM concept and it looks neat! However, I have a XAML binding error. I tried to replicate Jakob Christensen's answer provided in this link. I tried to debug and I think the issue is with the type of ObservableCollection that is created. It's an object type.
Thank you for helping!
Error
This is the XAML code for my view
<TabControl>
<TabItem DataContext="{Binding TabList[0]}" x:Name="Tab1" Header="Tab1" Margin="-2,-2,-2,2" >
<Grid>
<TextBox x:Name ="EnterNum1" Margin="300,100,300,300" Text="{Binding test1, Mode =TwoWay}"/>
<Button Name="RunBtn1" Command="{Binding Path=RunBtn1, Mode=TwoWay}" Content="RUN" HorizontalAlignment="Right" Width="180" Height="40" FontSize="18"/>
</Grid>
</TabItem>
<TabItem DataContext="{Binding TabList[1]}" x:Name="Tab2" Header="Tab2" >
<Grid>
<TextBox x:Name ="EnterNum2" Margin="300,100,300,300" Text="{Binding test2, Mode =TwoWay}" Grid.Column="1"/>
<Button Name="RunBtn2" Command="{Binding Path=RunBtn2, Mode=TwoWay}" Content="RUN" HorizontalAlignment="Right" Width="180" Height="40" FontSize="18"/>
</Grid>
</TabItem>
</TabControl>
This is the XAML.cs for my view
public ObservableCollection<object> TabList { get; set; }
public ImportData()
{
InitializeComponent();
TabList = new ObservableCollection<object>();
TabList.Add(new SampleViewModel1());
TabList.Add(new SampleViewModel2());
}
You should first set DataContext to TabControl or Window,
then you can bind the TabItem to the viewmodel(TabList) list item
XAML
<TabControl>
<TabItem DataContext="{Binding TabList[0]}" x:Name="Tab1" Header="Tab1" Margin="-2,-2,-2,2" >
<Grid>
<TextBox x:Name ="EnterNum1" Margin="300,100,300,240" Text="{Binding Test1, Mode =TwoWay}"/>
<Button Name="RunBtn1" Command="{Binding Path=RunBtn1, Mode=TwoWay}" Content="RUN" HorizontalAlignment="Right" Width="180" Height="40" FontSize="18"/>
</Grid>
</TabItem>
<TabItem DataContext="{Binding TabList[1]}" x:Name="Tab2" Header="Tab2" >
<Grid>
<TextBox x:Name ="EnterNum2" Margin="300,100,300,240" Text="{Binding Test2, Mode =TwoWay}" Grid.Column="1"/>
<Button Name="RunBtn2" Command="{Binding Path=RunBtn2, Mode=TwoWay}" Content="RUN" HorizontalAlignment="Right" Width="180" Height="40" FontSize="18"/>
</Grid>
</TabItem>
</TabControl>
XAML.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AllViewModel allViewModel = new AllViewModel();
allViewModel.TabList = new ObservableCollection<object>();
allViewModel.TabList.Add(new SampleViewModel1());
allViewModel.TabList.Add(new SampleViewModel2());
this.DataContext = allViewModel;
}
}
public class AllViewModel : INotifyPropertyChanged
{
private ObservableCollection<object> tabList;
public ObservableCollection<object> TabList
{
get => tabList;
set { tabList = value;RaiseChange("TabList"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class SampleViewModel1 : INotifyPropertyChanged
{
private string test1 = "test1";
private ICommand runBtn1;
public string Test1
{
get => test1;
set { test1 = value;RaiseChange("Test1"); }
}
public ICommand RunBtn1
{
get => runBtn1;
set { runBtn1 = value;RaiseChange("RunBtn1"); }
}
public SampleViewModel1()
{
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class SampleViewModel2 : INotifyPropertyChanged
{
private string test2 = "test2";
private ICommand runBtn2;
public string Test2
{
get => test2;
set { test2 = value; RaiseChange("Test2"); }
}
public ICommand RunBtn2
{
get => runBtn2;
set { runBtn2 = value; RaiseChange("RunBtn2"); }
}
public SampleViewModel2()
{
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
run result

Access and edit Image inside Button on Button click in code behind

I have a Listview built like this:
<ListView x:Name="listprimi" RelativePanel.Below="primi" ItemsSource="{x:Bind obs_prims2}" HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Tag="{Binding id}" Grid.Column="0" Padding="0" BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="100" Background="White" Click="selectMeal0">
<Image Name="sel0" Width="80" Height="80" Source="Images/ic_uncheck.png" RelativePanel.AlignLeftWithPanel="True" />
</Button>
<Image Width="120" Height="120" Margin="30,0,0,0" Source="{Binding idImg}" RelativePanel.AlignLeftWithPanel="True" />
<TextBlock Text="{Binding descr}" RelativePanel.AlignHorizontalCenterWithPanel="True" Height="100" Name="namemeal" Padding="60,15" Foreground="Gray" FontSize="26.7"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I would like to change the image named "sel0" which is inside the button when the button is clicked. I have set the code behind function selectMeal0 but I have no idea on how to do it.
In addition I would also like to change the images of all the other elements of the list in the same function.
I have tried something like this but it doesn't work.
UPDATE:
This is the class
public class Pasto : INotifyPropertyChanged
{
public string id { get; set; }
public string descr { get; set; }
public ImageSource idImg { get; set; }
private ImageSource imgChecked;
public ImageSource ImgChecked {
get { return imgChecked; }
set
{
if (imgChecked != value)
{
imgChecked = value;
OnPropertyChanged("ImgChecked");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
I've changed the ListView like this:
<ListView x:Name="listprimi" RelativePanel.Below="primi" ItemsSource="{x:Bind obs_prims2}" HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Tag="{Binding id}" Grid.Column="0" Padding="0" BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="100" Background="White" Click="selectMeal0">
<Image Name="sel0" Width="80" Height="80" Source="{Binding ImgChecked}" RelativePanel.AlignLeftWithPanel="True" />
</Button>
<Image Width="120" Height="120" Margin="30,0,0,0" Source="{Binding idImg}" RelativePanel.AlignLeftWithPanel="True" />
<TextBlock Text="{Binding descr}" RelativePanel.AlignHorizontalCenterWithPanel="True" Height="100" Name="namemeal" Padding="60,15" Foreground="Gray" FontSize="26.7"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
so that the image I'd like to edit is ImageChecked in the class.
The function selectMeal should change all the images to "unchecked" and then the selected item's image to "checked".
in selectMeal0, you get access to the sender object, which is a Button in this case. The Button have Content property, which in turn containts the Image. At this point you can do anything to the Image.
BUT
you can also bind the source of the image to a property of your model. And make change to the model to update the image.
In order to change Image inside your DataTemplate of your ListView, you should change the necessary item from your collection on button click:
So, you have a collection obs_prims2 as ItemsSource for ListView. Then you need to take the the one item from your collection obs_prims2. For example:
var item=obs_prims2.FirstOrDefault();
then set new Image address:
item.idImg="C:/1.png";
Moreover, your Model class should implement INotifyPropertyChanged interface to show any changes. For example:
public class Book : INotifyPropertyChanged
{
private string title;
public string Title {
get { return title; }
set {
title = value;
OnPropertyChanged("Title");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(String info)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
Update:
To get an item that you want, then you can get item by index, like that
Person person = Persons[1];. For example:
private void FillDataGridByTypeCollection()
{
Persons.Add(new Person() { Id = 1, Name = "Ben" });
Persons.Add(new Person() { Id = 1, Name = "Joseph" });
Persons.Add(new Person() { Id = 1, Name = "Jon" });
Persons.Add(new Person() { Id = 1, Name = "Magnus Montin" });
Persons.Add(new Person() { Id = 1, Name = "Andy" });
Person person = Persons[1];
}
private ObservableCollection<Person> persons = new ObservableCollection<Person>();
public ObservableCollection<Person> Persons
{
get { return persons; }
set { persons = value; }
}
Model:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}

WPF ObservableCollection not updating view

this is xaml part
<ItemsControl x:Name="EventsTop">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,1,0,0">
<Button Content="{Binding Name}" Template="{DynamicResource ButtonFirst}" Height="50" Margin="15,0,0,0" Padding="10,0,15,0" FontSize="19" FontFamily="/Resources/Fonts/Font Awesome/#FontAwesome" BorderThickness="5,0,0,0" BorderBrush="#8CC152" Background="#2980B9" HorizontalContentAlignment="Left" Foreground="Black" Click="TabOpen" Tag="{Binding Id}"></Button>
<StackPanel Background="#2980B9" Margin="15,0,0,5" Visibility="Collapsed" AllowDrop="True" Tag="{Binding Id}" Drop="RowDrop">
<Border BorderThickness="5,0,0,0" BorderBrush="#8CC152">
<StackPanel>
<DockPanel LastChildFill="False">
<Label DockPanel.Dock="Left" Width="140" Content="Date" FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Label DockPanel.Dock="Left" Width="190" Content="Event" FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Label DockPanel.Dock="Left" Width="100" Content="Select" FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
</DockPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="150">
<ItemsControl ItemsSource="{Binding Details}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel LastChildFill="False">
<Label Content="{Binding Date}" DockPanel.Dock="Left" Width="140" FontSize="19" BorderThickness="0" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Label Content="{Binding EventName}" DockPanel.Dock="Left" Width="165" FontSize="19" BorderThickness="0" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Border Width="97">
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding Checked}"></CheckBox>
</Border>
<Button Width="25" DockPanel.Dock="Left" Content="" BorderThickness="0" Background="Transparent" FontFamily="/Resources/Fonts/Font Awesome/#FontAwesome"></Button>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
this is xaml.cs
private void WindowLoaded(object sender, RoutedEventArgs e)
{
EventHelper eventHelper = new EventHelper();
TopEvents = eventHelper.GetSports(EventHelper.EventGroup.Top);
foreach (Sport item in TopEvents)
{
item.Name = "\uf196 " + item.Name;
}
EventsTop.ItemsSource = TopEvents;
AllEvents = eventHelper.GetSports(EventHelper.EventGroup.All);
foreach (Sport item in AllEvents)
{
item.Name = "\uf196 " + item.Name;
}
EventsAll.ItemsSource = AllEvents;
Sport.ItemsSource = eventHelper.GetSports(EventHelper.EventGroup.All);
}
private void RowMouseDown(object sender, MouseButtonEventArgs e)
{
DockPanel currentRow = (DockPanel) sender;
int rowOffset = Convert.ToInt32(currentRow.Tag);
DragDrop.DoDragDrop(currentRow,rowOffset,DragDropEffects.Copy);
}
private void RowDrop(object sender, DragEventArgs e)
{
int rowOffset = (int) e.Data.GetData(typeof (int));
AllEvents[0].Name = "1";
}
Also my model in collection
class Sport : INotifyPropertyChanged
{
private int _id;
private string _name = string.Empty;
private ObservableCollection<Details> _details = new ObservableCollection<Details>();
public int Id
{
get { return _id; }
set { _id = value; }
}
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged("Content");
}
}
public ObservableCollection<Details> Details
{
get { return _details; }
set { _details = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
MessageBox.Show(info);
}
}
}
So when I am changing property its throwing MessageBox but not updating GUI.
I xaml.cs I am calling methods GetEvents thats
return ObservableCollection
I want to change Name in Sport which is in ObservableCollaction<Sport> AllEvents
You can see it in RowDrop method in xaml.cs
In debugging I notice that AllEvents[0].Name was changed but view was not updating
UPDATE
Part of ObservabelCollection declaration
public MainPage()
{
InitializeComponent();
AllEvents = new ObservableCollection<Sport>();
TopEvents = new ObservableCollection<Sport>();
EventsTop.ItemsSource = TopEvents;
EventsAll.ItemsSource = AllEvents;
}
private ObservableCollection<Sport> AllEvents;
private ObservableCollection<Sport> TopEvents;
UPDATE SECOND
I caught that when I am using window activated event it is working
I found solution.
So, ObservableCollection is working very well but,It needs to be refreshed
for appearing in view and for it we need to use
CollectionViewSource.GetDefaultView(ObservableCollection).Refresh()
method for it
I think it will help someone
The problem with property named passed to NotifyPropertyChanged method. The name of parameter should be property name. Please change the Name property as
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged("Name");
}
}
Use CallerMemberNameAttribute to avoid having to get the name correct and allowing refactoring:
private void NotifyPropertyChanged([CallerMemberName] string info = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
MessageBox.Show(info);
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged(); //now no need to specify
}
}
Every property setter should notify property change, so:
public IEnumerable<Details> Details //note IEnumerable, no calling code needs to know its concrete type
{
get { return _details; }
set
{
_details = value;
NotifyPropertyChanged();
}
}
And with an observable range collection you could do this:
private readonly ObservableRangeCollection<Details> _details = new ObservableRangeCollection<Details>();
public IEnumerable<Details> Details
{
get { return _details; }
set { _details.Replace(value); }
}
From MSDN.
Occurs when an item is added, removed, changed, moved, or the entire
list is refreshed.
The changed does not mean when child properties are changed, but when you change the item at any index.
So when you modify a collection item you will need to notify the binding that the property was changed. From your window's viewmodel after you have modified the item in the collection, you would notify that the collection was changed.
NotifyPropertyChanged("AllEvents");

Update ListBox Items when there are changes in property of element in ObservableCollection

I am a newbie with windows phone development. I have a class named 'State'. It keeps the name and capital of the state. I have implemented INotifyPropertyChanged Interface.
public class State:INotifyPropertyChanged
{
private string _name;
private string _capital;
public State() { }
public State(string name, string capital)
{
this.Name=name;
this.Capital=capital;
}
public string Name
{ get
{
return _name;
}
set
{
_name=value;
OnPropertyChanged(this,"Name");
OnPropertyChanged(this, "Name");
}
}
public string Capital
{
get
{
return _capital;
}
set
{
_capital = value;
OnPropertyChanged(this, "Capital");
OnPropertyChanged(this, "Name");
}
}
public override string ToString()
{
return (Name + " " + Capital );
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(object sender,string Property)
{
if (PropertyChanged != null)
{
PropertyChanged(sender, new PropertyChangedEventArgs(Property));
}
}
}
The ObservableCollection maintains my list of states. I want to update the changes in one property of one element of the Collection and reflect the changes in ListBox. However the changes are not reflected. Here is my MainPage class. I change the property value on button click event.
public partial class MainPage : PhoneApplicationPage
{
private ObservableCollection<State> MyStatelist;
public MainPage()
{
InitializeComponent();
MyStatelist = new ObservableCollection<State>();
MyStatelist.Add(new State("State1","Capital1"));
States.ItemsSource = MyStatelist;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyStatelist[0].Name = "Abcd";
t1.Text = MyStatelist[0].Name;
}
}
Here is my XAML code
<ListBox x:Name="States" Margin="0,10" ItemsSource="{Binding MyStatelist Mode=TwoWay}" ScrollViewer.VerticalScrollBarVisibility="Visible" Background="White" Foreground="Black" Height="Auto" Width="Auto" >
</ListBox>
Is there anyway i can notify the listbox that it has to update.
Thanks A Lot!!
You are not binding to the properties yet. Use this instead:
<ListBox x:Name="States" Margin="0,10" ScrollViewer.VerticalScrollBarVisibility="Visible" Background="White" Foreground="Black" Height="Auto" Width="Auto" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="Name" />
<Binding Path="Capital" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You bind ObservableCollection<State> twice. First, you create new object in MainPage constructor. And this is enough. When you do it in XAML ItemsSource="{Binding MyStatelist Mode=TwoWay}", new instance of ObservableCollection<State> is created. That's why MyStatelist[0].Name = "Abcd" doesn't work because MyStatelist is not set as the source of items anymore. Just remove the binding in XAML.
One more thing. You have to add ItemTemplate to your ListBox and correctly bind properties of State class. Here's my example that works:
<ListBox x:Name="States" Margin="0,10"
Grid.Row="1"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Background="White"
Foreground="Black"
Height="Auto"
Width="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="0, 0, 12, 0"/>
<TextBlock Text="{Binding Capital}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

WPF Binding SelectedItem in DataGrid

So, I have a TabControl binded to a list of projects (each tab is a one project) - that works fine. The content of each tab is a DataGrid with a list of project's employees - that works fine as well. Now, I want to show some information on employee currently selected on DataGrid. Here's some code:
MainWindow.xaml file:
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
<DataTemplate x:Key="ContentTemplate">
<DataGrid ItemsSource="{Binding Employees}" SelectedItem="{Binding SelectedEmployee, Mode=TwoWay}" SelectionMode="Extended" SelectionUnit="FullRow" Name="employeesList">
</DataGrid>
</DataTemplate>
</Window.Resources>
and later, I want to test this binding by simply writing it in label:
<Label Name="emp" Content="{Binding SelectedEmployee}"></Label>
and MainWindowViewModel:
public Employee SelectedEmployee { get { return selectedEmployee; }
set
{
if (selectedEmployee != value)
{
selectedEmployee = value;
NotifyPropertyChanged("SelectedEmployee");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
I am kind of a newbie to WPF, I've read some tips but they don't help. The label 'emp' does not show anything. What am I missing?
You are not notifying that your property has changed, Try this
public Employee SelectedEmployee
{
get { return selectedEmployee; }
set
{
if (selectedEmployee != value)
{
selectedEmployee = value;
LastName = value;
NotifyPropertyChanged("SelectedEmployee"); //NotifyPropertyChanged("SelectedItem");
}
}
}
Test:
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication6"
Title="MainWindow" Height="350" Width="763" Name="UI" >
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</Window.Resources>
<Grid>
<DataGrid ItemsSource="{Binding ElementName=UI,Path=Employees}" SelectedItem="{Binding ElementName=UI,Path=SelectedEmployee}" SelectionMode="Extended" SelectionUnit="FullRow" Name="employeesList" Margin="0,41,0,0" />
<Label Content="{Binding ElementName=UI,Path=SelectedEmployee.Name}" Height="28" HorizontalAlignment="Left" Name="label1" VerticalAlignment="Top" Width="288" />
<Label Content="{Binding ElementName=employeesList,Path=SelectedItem.Name}" Height="28" HorizontalAlignment="Left" Name="label2" VerticalAlignment="Top" Width="288" Margin="294,0,0,0" />
</Grid>
</Window>
Code:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<Employee> _employees = new ObservableCollection<Employee>();
private Employee _selectedEmployee;
public MainWindow()
{
InitializeComponent();
Employees.Add(new Employee { Name = "sa_ddam213" });
}
public ObservableCollection<Employee> Employees
{
get { return _employees; }
set { _employees = value; }
}
public Employee SelectedEmployee
{
get { return _selectedEmployee; }
set { _selectedEmployee = value; NotifyPropertyChanged("SelectedEmployee"); }
}
/// <summary>
/// Notifies the property changed.
/// </summary>
/// <param name="info">The info.</param>
public void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
public class Employee
{
public string Name { get; set; }
}
This seems to work as expected, or am I missing something?

Categories