Binding not working? - c#

Most of my bindings are working fine but one just displays: Test.Models.PersonModel
The property ("Name") where I like to bind to is in this class.
Here the part where I bind:
<ItemsControl ItemsSource="{Binding Persons}">
<StackPanel Margin="24, 4, 4, 4"
Orientation="Horizontal">
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}"
FontFamily="{StaticResource PhoneFontFamilyLight}"
Text="{Binding Name}"
VerticalAlignment="Center"/>
</StackPanel>
</ItemsControl>
Persons is a OberservableCollection of the type PersonModel. Here the code of the PersonModel:
public class PersonModel : INotifyPropertyChanged
{
private string _name = null;
public string Name
{
get { return _name; }
set { _name = value; NotifyPropertyChanged("Name"); }
}
private BitmapImage _profilpicture = null;
public BitmapImage ProfilPicture
{
get { return _profilpicture; }
set { _profilpicture = value; NotifyPropertyChanged("ProfilPicture"); }
}
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}

You should use ItemTemplate (msdn):
<ItemsControl ItemsSource="{Binding Persons}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="24, 4, 4, 4"
Orientation="Horizontal">
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}"
FontFamily="{StaticResource PhoneFontFamilyLight}"
Text="{Binding Name}"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Related

Binding and changing a listView dynamically using MVVM

I have an object consisting of a string and a string of arrays. I'm binding the string to a comboBox but what I want to also do is bind the array of that object to a listview and have it change dynamically depending on combox box value. The values in the array aren't populating, only the dataType of the array. I'm not married to using a listview but I thought it would be easiest.
Model -
namespace DataBinding_WPF.Model
{
public class ExampleModel { }
public class Example : INotifyPropertyChanged
{
private string _name;
private string[] _ids;
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
RaisePropertyChanged("Name");
}
}
}
public string[] IDs
{
get => _ids;
set
{
if (_ids != value)
{
_ids = value;
RaisePropertyChanged("IDs");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(property));
}
}
}
ViewModel -
namespace DataBinding_WPF.ViewModel
{
public class ExampleViewModel
{
public ObservableCollection<Example> Examples
{
get;
set;
}
public void LoadExample()
{
ObservableCollection<Example> examples = new ObservableCollection<Example>();
examples.Add(new Example { Name = "Mark", IDs = new string[] { "123", "456" }});
examples.Add(new Example { Name = "Sally", IDs = new string[] { "789","101112" }});
Examples = examples;
}
}
}
XAML -
<Grid>
<StackPanel HorizontalAlignment = "Left" >
<ComboBox HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="120"
ItemsSource="{Binding Path=Examples}"
SelectedItem="{Binding Path=Name, Mode=TwoWay}"
DisplayMemberPath="Name"/>
<ListView x:Name="myListView"
ItemsSource="{Binding Path=Examples}"
SelectedValue="{Binding Path=IDs}"
Height="200" Margin="0,50,0,0"
Width="Auto"
VerticalAlignment="Top"
Background="AliceBlue">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<CheckBox
Name="myCheckBox"
IsChecked="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType=ListViewItem}}"
Margin="5, 0"/>
<TextBlock Text= "{Binding Path=IDs}" FontWeight="Bold" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
If you want to show in ListBox the Ids of selected item in comboBox.
You need to add SelectedItem property to your VM which also must implement INotifyPropertyChanged interface.
namespace DataBinding_WPF.ViewModel
{
public class ExampleViewModel : INotifyPropertyChanged
{
public ObservableCollection<Example> Examples
{
get;
set;
}
// SelectedItem in the ComboBox
// SelectedItem.Ids will be ItemsSource for the ListBox
private Example _selectedItem;
public Example SelectedItem
{
get => _selectedItem;
set {
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem));
}
}
// SelectedId in ListView
private string _selectedId;
public string SelectedId
{
get => _selectedId;
set {
_selectedId= value;
OnPropertyChanged(nameof(SelectedId));
}
}
public void LoadExample()
{
ObservableCollection<Example> examples = new ObservableCollection<Example>();
examples.Add(new Example { Name = "Mark", IDs = new string[] { "123", "456" }});
examples.Add(new Example { Name = "Sally", IDs = new string[] { "789","101112" }});
Examples = examples;
}
}
}
XAML
<Grid>
<StackPanel HorizontalAlignment = "Left" >
<ComboBox HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="120"
ItemsSource="{Binding Path=Examples}"
SelectedItem="{Binding SelectedItem}"
DisplayMemberPath="Name"/>
<ListView x:Name="myListView"
ItemsSource="{Binding SelectedItem.Ids}"
SelectedItem="{Binding SelectedId}"
Height="200" Margin="0,50,0,0"
Width="Auto"
VerticalAlignment="Top"
Background="AliceBlue">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<CheckBox
Name="myCheckBox"
IsChecked="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType=ListViewItem}}"
Margin="5, 0"/>
<TextBlock Text= "{Binding}" FontWeight="Bold" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
There could several solutions to your case but most common and proprietary way is to use ValueConverter.
For this example i'll assume you have grid in the Window control. You need to add static resource:
<Window.Resources>
<local:ArrayValueConverter x:Key="arrayConverter"/>
</Window.Resources>
Then in your ListView's DataTemplate add Converter:
<TextBlock Text= "{Binding Path=IDs, Converter={StaticResource arrayConverter}}" FontWeight="Bold" />
ValueConverter himself:
public class ArrayValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string[] arr) {
return string.Join(',', arr);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}

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

Editable Combobox dont get item wpf

I have a combobox that I set isEditable = true but when I press Down arrow from keyboard I get this message
MoalemYar.DataClass.DataTransferObjects+StudentsDto
Instead of my selected item, this is my combobox
<ComboBox
x:Name="cmbEditStudent"
IsEditable="True"
SelectedValue="{Binding LName}"
SelectedValuePath="Id">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding LName}" />
<TextBlock Text=" - " />
<TextBlock Text="نام پدر(" />
<TextBlock Text="{Binding FName}" />
<TextBlock Text=")" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Try this hope it will helps you
<ComboBox Height="25" Margin="80,12,12,0" Name="comboBox1" VerticalAlignment="Top"
ItemsSource="{Binding StudentList}" IsEditable="True" TextSearch.TextPath="StudentName">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding StudentName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
By default, the first item in a combo box is selected by the down arrow, then you can press up/down arrows keys to change the selected item accordingly.
Try the following code.
In XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox
x:Name="cmbEditStudent"
IsTextSearchEnabled="True"
TextSearch.TextPath = "Name"
IsEditable="True"
ItemsSource="{Binding StudentsList}"
SelectedItem="{Binding SelectedStudent}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding LName}" />
<TextBlock Text=" - " />
<TextBlock Text="نام پدر(" />
<TextBlock Text="{Binding FName}" />
<TextBlock Text=")" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Width="200" Height="20" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
In its View Model
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<Student> studentsList = new ObservableCollection<Student>();
public ObservableCollection<Student> StudentsList
{
get { return studentsList; }
set
{
studentsList = value;
NotifyPropertyChanged();
}
}
private Student selectedStudent;
public Student SelectedStudent
{
get { return selectedStudent; }
set
{
selectedStudent = value;
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
StudentsList.Add(new Student("Paul", "LName1", "FName1"));
StudentsList.Add(new Student("Alex", "LName2", "FName2"));
StudentsList.Add(new Student("Steve", "LName3", "FName3"));
}
#region Notify Property
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propName = null)
{
if (!string.IsNullOrWhiteSpace(propName))
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}));
}
}
#endregion
}
Student Class
public class Student : NotifiableBase
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
NotifyPropertyChanged();
}
}
private string lName;
public string LName
{
get { return lName; }
set
{
lName = value;
NotifyPropertyChanged();
}
}
private string fName;
public string FName
{
get { return fName; }
set
{
fName = value;
NotifyPropertyChanged();
}
}
public Student(string name, string lName, string fName)
{
this.name = name;
this.lName = lName;
this.fName = fName;
}
}
NotifiableBase
public class NotifiableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propName = null)
{
if (!string.IsNullOrWhiteSpace(propName))
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}));
}
}
}

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>

Categories