簡體   English   中英

使用Josh Smith的WPF MVVM演示應用程序實現ListView過濾器

[英]Implementing a ListView Filter with Josh Smith's WPF MVVM Demo App

我一直在嘗試擴展Josh Smith的演示MVVM應用程序,以便更好地理解它背后的原理,並且當我嘗試使用ListView在View上實現過濾器功能時,我遇到了障礙。

我花了幾個小時研究和涉獵,但它只是沒有用。

我的第一步是將視圖中的文本框綁定到ViewModel中的屬性:

<TextBox Height="25" Name="txtFilter" Width="150" Text="{Binding Path=Filter, UpdateSourceTrigger=PropertyChanged}"/>

這在我的VM中匹配:

public string Filter
    {
        get { return this.filter; }
        set
        {
            this.filter = value;
            OnFilterChanged();
        }
    }

我的VM使用ObservableCollection作為數據源,但我在閱讀教程后嘗試將其轉換為ICollectionView:

internal ObservableCollection<StaffViewModel> InnerStaff { get; set; }
    internal CollectionViewSource CvsStaff { get; set; }
    public ICollectionView AllStaff
    {
        get { return CvsStaff.View; }
    }

在我的構造函數中,我指定:

CvsStaff = new CollectionViewSource();
CvsStaff.Source = this.InnerStaff;
CvsStaff.Filter += ApplyFilter;

當我的Filter屬性更新時,它調用OnFilterChanged,它是:

private void OnFilterChanged()
    {
        CvsStaff.View.Refresh();
    }

我的ApplyFilter函數是:

void ApplyFilter(object sender, FilterEventArgs e)
    {
        StaffViewModel svm = (StaffViewModel)e.Item;

        if (this.Filter.Length == 0)
        {
            e.Accepted = true;
        }
        else
        {
            e.Accepted = svm.LastName.Contains(Filter);
        }
    }

我做過一個愚蠢的錯誤,任何人都可以幫我發現嗎? 我是WPF和MVVM模式的新手,所以我還在學習!

編輯

在視圖中我將集合綁定到:

<CollectionViewSource
  x:Key="StaffGroup"
  Source="{Binding Path=AllStaff}"
  />

和ListView是這樣的:

<ListView
      Name="staffList"
      AlternationCount="2" 
      DataContext="{StaticResource StaffGroup}" 
      ItemContainerStyle="{StaticResource StaffItemStyle}"
      ItemsSource="{Binding}"
        Grid.Row="1">

綁定不正確。 你需要做一些改變。 首先要確保正確設置DataContext。 通常,您將在ListView的父級上執行此操作,而不是直接在ListView控件上設置它。 這可能是UserControl / Window /等。

所以假設你有一個視圖模型:

public class MainViewModel
{
    public MainViewModel()
    {
        //Create some fake data 
        InnerStaff = new ObservableCollection<StaffViewModel>();
        InnerStaff.Add(new StaffViewModel {FirstName = "Sue", LastName = "Bucknell"});
        InnerStaff.Add(new StaffViewModel {FirstName = "James", LastName = "Bucknell"});
        InnerStaff.Add(new StaffViewModel {FirstName = "John", LastName = "Harrod"});

        CvsStaff = new CollectionViewSource();
        CvsStaff.Source = this.InnerStaff;
        CvsStaff.Filter += ApplyFilter;
    }

    private string filter;

    public string Filter
    {
        get { return this.filter; }
        set
        {
            this.filter = value;
            OnFilterChanged();
        }
    }

    private void OnFilterChanged()
    {
        CvsStaff.View.Refresh();
    }

    internal ObservableCollection<StaffViewModel> InnerStaff { get; set; }
    internal CollectionViewSource CvsStaff { get; set; }
    public ICollectionView AllStaff
    {
        get { return CvsStaff.View; }
    }

    void ApplyFilter(object sender, FilterEventArgs e)
    {
        StaffViewModel svm = (StaffViewModel)e.Item;

        if (string.IsNullOrWhiteSpace(this.Filter) || this.Filter.Length == 0)
        {
            e.Accepted = true;
        }
        else
        {
            e.Accepted = svm.LastName.Contains(Filter);
        }
    }
}

假設您有一個Window MainWindow.cs(后面的代碼),您可以(對於此示例)在此處連接DataContext。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

然后你有幾個選擇來進行綁定,你可以在XAML或代碼中指定你的CollectionViewSource,但你已經做到了。 即xaml one,鍵x:key =“StaffGroup”,VM為CvsStaff。 假設我們完全擺脫了xaml並使用VM one,這是正確設置的。 然后你將使用ItemsSource屬性綁定,如下所示:

<ListView Name="staffList" 
      AlternationCount="2" 
      ItemsSource="{Binding AllStaff}" 
      Grid.Row="1" />

同樣小的事情,我已經更改過濾器來檢查空值和空格。 您可能還需要將其更改為不區分大小寫。

我在這里沒有提到但另一件事是至關重要的是在你的StaffViewModel上實現INotifyPropertyChanged - 我假設你有,如果不是這里有一些代碼。 您通常也會在大多數視圖模型上執行此操作,以通知視圖屬性的更改。

internal class StaffViewModel : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            OnPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            OnPropertyChanged("LastName");
        }
    }
    public override string ToString()
    {
        return string.Format("{0} {1}", FirstName, LastName);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM