使用MVVM绑定ObservableCollection

lha*_*han 6 c# observablecollection mvvm windows-phone-8

我正在尝试将应该是一个非常基本的MVVM示例放在一起,但是我无法让它工作.基本上,我想将a绑定ObservableCollection到a ListBox,并为用户提供搜索选项以搜索其他项目.在搜索时,ListBox应该刷新,因为集合将会改变.这是我的代码:

模型:

public class Item
   public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

视图模型:

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

视图:

<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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

最后,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;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以会发生什么,我可以看到第一次加载默认项目,但是当我搜索时,列表不会刷新.它现在都是硬编码所以如果搜索确实有效,我应该看到3个项目,无论他们搜索什么.

我注意到的是,如果我在ViewModel中设置断点RaisePropertyChanged,this.PropertyChanged始终为null,因此它永远不会在if语句中.我已经看到INotifyPropertyChanged了在模型上使用的示例,但在这种情况下,因为我需要在集合更改时收到通知,所以在视图模型上使用似乎是正确的.这可能是错的,但我不确定如何设置它.

谁能看到我做错了什么?

小智 5

尝试这样做

  1. 将 ItemSource 设置为 Items

  2. 清除和添加数据项

    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" }); 
    }
    
    Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。