【问题标题】:WPF MVVM DataGrid filtering using ComboBoxWPF MVVM DataGrid 过滤使用组合框
【发布时间】:2017-09-02 14:17:24
【问题描述】:

我有一个 WPF MVVM 应用程序,其中包含一个绑定到 ViewModel 类中相同实体列表的 DataGrid 和一个 ComboBox。 我想通过 ComboBox 选择过滤 DataGrid 条目,这样做的正确方法是什么?由于我正在使用 MVVM,因此我想通过数据绑定来实现这一点,并避免后面出现无用的代码。

我的 XAML 代码如下所示

<DataGrid ItemsSource="{Binding Posts}" AutoGenerateColumns="False" IsReadOnly="True">
   <DataGrid.Columns>
      <DataGridTextColumn Header="Id" Binding="{Binding Id}" />
      <DataGridTextColumn Header="Title" Binding="{Binding Title}" />
      <DataGridTextColumn Header="BlogUrl" Binding="{Binding Blog.Url}" />
   </DataGrid.Columns>
</DataGrid>

<ComboBox ItemsSource="{Binding Posts}"
          DisplayMemberPath="Blog.Url" />

视图模型

public class MainWindowViewModel
{
    private SqliteDbContext context;
    public List<Post> Posts { get; set; }

    public MainWindowViewModel()
    {
        context = new SqliteDbContext();
        Posts = context.Posts.Include(p => p.Blog).ToList();
    }
}

此外,使用此代码,我的 ComboBox 会显示重复的 Urls,我如何区分这些值?

谢谢。

【问题讨论】:

  • 引用另一个so

标签: c# wpf xaml mvvm data-binding


【解决方案1】:

这应该可以解决问题。

视图模型

public class MainWindowViewModel
{
    private SqliteDbContext context;

    public ObservableCollection<Post> Posts { get; set; }
    private string _selectedUrl;
    public ICollectionView PostsView { get; set; }
    public MainWindowViewModel()
    {
        context = new SqliteDbContext();
        Posts = new ObservableCollection<Post>(context.Posts.Include(p => p.Blog));
        PostsView = new CollectionViewSource { Source = Posts }.View;
        PostsView.Filter = post => SelectedUrl == null || SelectedUrl == ((Post)post).Blog.Url;
    }

    public string SelectedUrl
    {
        get
        {
            return _selectedUrl;
        }
        set
        {
            _selectedUrl = value;
            PostsView.Refresh();
        }
    }
}  

XAML

<DataGrid ItemsSource="{Binding PostsView}" AutoGenerateColumns="False" IsReadOnly="True">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Id" Binding="{Binding Id}" />
        <DataGridTextColumn Header="Title" Binding="{Binding Title}" />
        <DataGridTextColumn Header="BlogUrl" Binding="{Binding Blog.Url}" />
    </DataGrid.Columns>
</DataGrid>

<ComboBox ItemsSource="{Binding Posts}"
          DisplayMemberPath="Blog.Url" 
          SelectedValuePath="Blog.Url"
          SelectedValue="{Binding SelectedUrl}"/>

【讨论】:

    【解决方案2】:

    您可以将ComboBox 绑定到您在视图模型中创建的唯一网址的集合。

    然后您可以通过将ComboBoxSelectedItem 属性绑定到过滤Posts 源集合的视图模型的源属性来过滤DataGrid

    请参考以下代码示例。

    查看模型:

    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private readonly SqliteDbContext context;
        private readonly List<Post> _allPosts;
    
        public MainWindowViewModel()
        {
            context = new SqliteDbContext();
            _allPosts = context.Posts.Include(p => p.Blog).ToList();
            _posts = _allPosts;
            Urls = _allPosts.Where(p => p.Blog != null && !string.IsNullOrEmpty(p.Blog.Url)).Select(p => p.Blog.Url).ToList();
        }
    
        private List<Post> _posts;
        public List<Post> Posts
        {
            get { return _posts; }
            set { _posts = value; NotifyPropertyChanged(); }
        }
    
        public List<string> Urls { get; set; }
    
        private string  _url;
        public string  Url
        {
            get { return _url; }
            set
            {
                _url = value; NotifyPropertyChanged();
                Posts = _allPosts.Where(p => p.Blog != null && p.Blog.Url == _url).ToList();
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    查看:

    <DataGrid ItemsSource="{Binding Posts}" AutoGenerateColumns="False" IsReadOnly="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="{Binding Id}" />
            <DataGridTextColumn Header="Title" Binding="{Binding Title}" />
            <DataGridTextColumn Header="BlogUrl" Binding="{Binding Blog.Url}" />
        </DataGrid.Columns>
    </DataGrid>
    
    <ComboBox ItemsSource="{Binding Urls}" SelectedItem="{Binding Url}" />
    

    【讨论】:

      猜你喜欢
      • 2020-06-06
      • 2023-03-18
      • 1970-01-01
      • 2013-01-23
      • 2012-04-05
      • 1970-01-01
      • 2019-03-15
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多