微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

根据同一ListView中的选定项目属性过滤ICollectionView-MVVM

如何解决根据同一ListView中的选定项目属性过滤ICollectionView-MVVM

我似乎无法解决。任何帮助表示赞赏。

编辑:通过结合@BionicCode提供的Filter逻辑,通过this post在XMAL中实现ListView选择并添加简单的bool Converter er来实现可见性,从而实现了解决方案。我还发现,Items Control也可以在这种情况下工作,并允许每个this post进行更好的控制。

我有一个ListView:

编辑:不幸的是,这还不够。两个ListViews将起作用。请注意添加的命名空间xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"。此外,我添加了“返回”按钮,允许用户返回以选择其他类别。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"  
        xmlns:vm="clr-namespace:WpfApp1.viewmodels" 
        Title="MainWindow" Height="300" Width="500" WindowStartupLocation="CenterScreen">
    <Window.DataContext>
        <vm:Mainviewmodel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDeFinitions>
            <ColumnDeFinition Width="100"/>
            <ColumnDeFinition/>
            <ColumnDeFinition/>
            <ColumnDeFinition/>
        </Grid.ColumnDeFinitions>
        <Grid.RowDeFinitions>
            <RowDeFinition Height="15"/>
            <RowDeFinition/>
        </Grid.RowDeFinitions>

        <Grid Grid.Column="0" Grid.Row="1">
            <Button x:Name="BackBtn" Content="Back" Command="{Binding BacktoCatView}"/>
        </Grid>

        <Grid Grid.Column="1" Grid.Row="1"  >
            <ListView x:Name="CategoryListView" ItemsSource="{Binding CategoryView}" SelectedItem="{Binding SelectedCategory}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Category}"/>
                    </DataTemplate>
                </ListView.ItemTemplate>
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <i:InvokeCommandAction Command="{Binding SelectedCategoryCommand}" CommandParameter="{Binding SelectedItem,ElementName=CategoryListView}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ListView>
        </Grid>

        <Grid Grid.Column="1" Grid.Row="1" Visibility="{Binding IsBrandView,Converter={StaticResource VisibilityConverter}}">
            <ListView ItemsSource="{Binding BrandView}">
                <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Brand}"/>
                </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
    </Grid> </Window>

我有一个模特:

public class Car : NotifyPropertyChanged
{
    private string _brand;
    public string Brand
    {
        get => _brand;
        set
        {
            _brand = value;
            OnPropertyChanged();
        }
    }

    private string _category;
    public string Category
    {
        get => _category;
        set
        {
            _category = value;
            OnPropertyChanged();
        }
    }
}

ListView绑定到一个名为“ CategoryView”的ICollectionView,它基于Mainviewmodel中的一个ObservableCollection“ CarsCollection”。

编辑:每个Listview分别绑定到它们的ICollectionView,ala,“ CategoryView”和“ BrandView”。 SelectedCategory绑定到“ CategoryView”中的SelectedItem。

Mainviewmodel:

 public class Mainviewmodel : NotifyPropertyChanged
        {
            private ObservableCollection<Car> _carsCollection;
            public ObservableCollection<Car> CarsCollection
            {
                get { return _carsCollection; }
                set
                {
                    _carsCollection = value;
                    OnPropertyChanged();
                }
            }
    
            private ICollectionView _categoryView;
            public ICollectionView CategoryView
            {
                get { return _categoryView; }
                set
                {
                    _categoryView = value;
                    OnPropertyChanged();
                }
            }
    
            private ICollectionView _brandView;
            public ICollectionView BrandView
            {
                get { return _brandView; }
                set
                {
                    _brandView = value;
                    OnPropertyChanged();
                }
            }
    
            private Car _selectedCategory;
            public Car SelectedCategory
            {
                get { return _selectedCategory; }
                set
                {
                    _selectedCategory = value;
                    OnPropertyChanged();
                }
            }
            public ICommand BacktoCatView { get; private set; }
            public ICommand SelectedCategoryCommand { get; private set; }
    
            
            private bool _isBrandView;
            public bool IsBrandView
            {
                get { return _isBrandView; }
                set
                {
                    _isBrandView = value;
                    OnPropertyChanged();
                }
            }
    
            public Mainviewmodel()
            {
                CarsCollection = new ObservableCollection<Car>
                    {
                        new Car { Brand = "Chevy",Category = "Sedan" },new Car { Brand = "Mazda",Category = "Sports Car" },new Car { Brand = "Toyota",new Car { Brand = "Honda",new Car { Brand = "Volkswagon",new Car { Brand = "Tesla",new Car { Brand = "Dodge",new Car { Brand = "Jeep",Category = "Off Road" },};
    
                BacktoCatView = new RelayCommand(ShowCategoryView);
                SelectedCategoryCommand = new RelayCommand(FilterbyBrand);
                //Filter by Category on app start
                CategoryView = CollectionViewSource.Getdefaultview(CarsCollection);
                CategoryView.Filter = item => !IsDuplicate((IEnumerable<Car>)CategoryView.sourceCollection,(Car)item);
                //Setup BrandView for filtering
                BrandView = (CollectionView)new CollectionViewSource { Source = CarsCollection }.View;
    
                OnPropertyChanged("CategoryView");
                OnPropertyChanged("BrandView");
            }
    
            static bool IsDuplicate(IEnumerable<Car> collection,Car target)
            {
                foreach (var item in collection)
                {
                    // NOTE: Check only the items BEFORE the one in question
                    if (ReferenceEquals(item,target)) break;
                    // If more than one Category is present,only show one instance of it
                    if (item.Category == target.Category) return true;
                }
                return false;
            }
    
            private void ShowCategoryView()
            {
                IsBrandView = false;
            }
    
            public void FilterbyBrand()
            {
                IsBrandView = true;
                BrandView.Filter = item => (item as Car).Category.Equals(_selectedCategory.Category,StringComparison.OrdinalIgnoreCase);
                OnPropertyChanged("BrandView");
            }
        }
    }  

编辑:在名为“ Helpers”的新名称空间中,将IValueConverter添加到“ Converters”类中以处理可见性。我还在Utility命名空间中添加一个RelayCommand类,以简化ICommands的使用。

namespace WpfApp1.Helpers
{
    public class BoolToVisibilityConverter : IValueConverter
    {
        public object Convert(object value,Type targettype,object parameter,CultureInfo culture)
        {
            var boolValue = (bool)value;

            if (boolValue)
                return Visibility.Visible;

            return Visibility.Collapsed;
        }

        public object ConvertBack(object value,CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

一个过滤器发生在构造函数中:

    // Filter by Category
    CategoryView = CollectionViewSource.Getdefaultview(CarsCollection);
    CategoryView.Filter = item => !IsDuplicate((IEnumerable<Car>)CategoryView.sourceCollection,(Car)item);

使用以下方法删除Category的重复实例:

static bool IsDuplicate(IEnumerable<Car> collection,Car target)
    {
        foreach (var item in collection)
        {
            // NOTE: Check only the items BEFORE the one in question
            if (ReferenceEquals(item,target)) break;
            // If more than one Category is present,only show one instance of it
            if (item.Category == target.Category) return true;
        }
        return false;
    }

filter可以完美工作,并在CategoryListView中产生以下内容

Sedan
Sports Car
Off Road

挑战:

用户从ListView中选择“类别”时,我希望接下来对IListCollection应用第二个过滤器,以过滤ListView,以使用户选择的“ Category”中的每个“ Brand”都被选中显示在ListView中。

编辑:现在,当用户选择类别时,将向他们显示该特定Brand的{​​{1}}的列表。过滤对用户无缝进行。最重要的是,这为用户提供了应用程序启动时的可用类别的即时视图,并且不需要用户在组合框中找到所需的类别。

非常感谢@BionicCode提供的过滤逻辑帮助。

品牌过滤器和Category bool:

IsBrandView

解决方法

我通过结合@BionicCode提供的Filter逻辑解决了这个问题,根据这篇文章在XMAL中实现了ListView选择,并添加了一个简单的bool Converter er以提高可视性。

解决方案已添加到原始帖子中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。