I'm trying to put together what should be a very basic MVVM sample, but I'm having trouble getting it to work. Basically, I want to bind an ObservableCollection
to a ListBox
, and have a search option for the user to search for other items. Upon searching, the ListBox
should be refreshed as the collection will change. Here is my code:
Model:
public class Item
public string Name { get; set; }
}
ViewModel:
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<Item> _items { get; set; }
public ObservableCollection<Item> Items
{
get { return _items; }
set
{
_items = value;
RaisePropertyChanged("Items");
}
}
public void GetDefaultItems()
{
ObservableCollection<Item> temp = new ObservableCollection<Item>();
temp.Add(new Item() { Name = "abc" + " 1" });
temp.Add(new Item() { Name = "def" + " 2" });
temp.Add(new Item() { Name = "ghi" + " 3" });
Items = temp;
}
public void Search(string query)
{
ObservableCollection<Item> temp = new ObservableCollection<Item>();
temp.Add(new Item() { Name = query + " 1" });
temp.Add(new Item() { Name = query + " 2" });
temp.Add(new Item() { Name = query + " 3" });
Items = temp;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
View:
<Grid x:Name="LayoutRoot">
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="Name" Text="{Binding Name}" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
MainPage.xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBox x:Name="txtSearch"/>
<TextBlock Text="Items:" />
<views:ItemView x:Name="ItemsOnPage" />
</StackPanel>
</Grid>
and finally, MainPage.xaml.cs:
public partial class MainPage : PhoneApplicationPage
{
private ViewModel vm;
// Constructor
public MainPage()
{
InitializeComponent();
txtSearch.KeyUp += txtSearch_KeyUp;
vm = new ViewModel();
}
void txtSearch_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
vm.Search(txtSearch.Text);
}
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
vm.GetDefaultItems();
ItemsOnPage.DataContext = vm.Items;
}
}
So what happens is, I can see the default items load the first time but when I search, the list does not get refreshed. It is all hard-coded right now so if the search does work I should see 3 items for whatever they searched for.
What I've noticed though is that if I set up a breakpoint in the ViewModel at RaisePropertyChanged
, this.PropertyChanged
is always null, so it never makes it inside the if
statement. I've seen examples that use INotifyPropertyChanged
on the model, but in this case since I need to be notified when the collection changes, it seemed correct to use on the view model. This could be wrong, but I'm not sure how else to set it up.
Can anyone see what I'm doing wrong?
MVVM – WPF Data Bindings For data binding you need to have a view or set of UI elements constructed, and then you need some other object that the bindings are going to point to. The UI elements in a view are bound to the properties which are exposed by the ViewModel.
One more important difference is you can access ObservableCollection only from thread on which it was created where as list can be accessed fromany thread. Save this answer. Show activity on this post. I see no problem with that, other than a very marginal performance overhead.
An ObservableCollection is a dynamic collection of objects of a given type. Objects can be added, removed or be updated with an automatic notification of actions. When an object is added to or removed from an observable collection, the UI is automatically updated.
try doing this
set ItemSource to Items
Clear and Add Data Items
String preQuery="";
public void Search(string query)
{
if(preQuery==query)
return;
Items.Clear();
Items.Add(new Item() { Name = query + " 1" });
Items.Add(new Item() { Name = query + " 2" });
Items.Add(new Item() { Name = query + " 3" });
}
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With