【问题标题】:UWP AdvancedCollectionView filter not working with stringsUWP AdvancedCollectionView 过滤器不适用于字符串
【发布时间】:2023-03-21 18:40:02
【问题描述】:

我有一个来自 Windows Community Toolkit 版本 6.1.1AdvancedCollectionView,并试图用它来过滤掉 2 个字符串属性。

我创建了一个简单的应用程序来重现该问题:https://github.com/touseefbsb/UWP-Filter-List

它有一个文本框,用于在项目的 StartNumberEndNumber 属性之间进行过滤。

但是一旦我在其中输入文本“123”,它就会在 ListView 中不显示任何项目,而实际上它应该只显示第一项,基于测试逻辑。

代码

MainPage.xaml

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBox
        x:Name="SearchTicketBooksBox"
        Width="300"
        Header="Search"
        TextChanged="SearchTicketBooks_TextChanged" />
    <ListView
        x:Name="TicketBooksListView"
        Grid.Row="1"
        Margin="4,0,0,0"
        ItemsSource="{x:Bind ViewModel.TicketBooks}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="app1:TicketBookDto">
                <StackPanel Margin="20">
                    <TextBlock Text="{x:Bind StartNumber}" />
                    <TextBlock Text="{x:Bind EndNumber}" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

MainPage.xaml.cs

 public sealed partial class MainPage : Page
{
    public MainViewModel ViewModel { get; }
    public MainPage() { InitializeComponent(); ViewModel = new MainViewModel(); }

    private void SearchTicketBooks_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (ViewModel != null)
        {
            if (string.IsNullOrWhiteSpace(SearchTicketBooksBox.Text))
            {
                ViewModel.TicketBooks.Filter = _ => true;
            }
            else
            {
                ViewModel.TicketBooks.Filter = x => ((TicketBookDto)x).StartNumber == SearchTicketBooksBox.Text;
                //{
                //    var startNumber = Convert.ToInt32(((TicketBookDto)x).StartNumber);
                //    var endNumber = Convert.ToInt32(((TicketBookDto)x).EndNumber);
                //    var searchText = Convert.ToInt32(SearchTicketBooksBox.Text);
                //    return searchText >= startNumber && searchText <= endNumber;
                //};
            }
        }
    }

    private void Page_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        ViewModel.TicketBooks.Add(new TicketBookDto { StartNumber = "123", EndNumber = "456" });
        ViewModel.TicketBooks.Add(new TicketBookDto { StartNumber = "789", EndNumber = "987" });
    }
}

MainViewModel

public class MainViewModel : INotifyPropertyChanged
{
    private readonly ObservableCollection<TicketBookDto> _ticketBooksPrivate = new ObservableCollection<TicketBookDto>();
    private AdvancedCollectionView ticketBooks;
    public AdvancedCollectionView TicketBooks
    {
        get
        {
            if (ticketBooks is null)
            {
                ticketBooks = new AdvancedCollectionView(_ticketBooksPrivate, true);
                ticketBooks.ObserveFilterProperty(nameof(TicketBookDto.StartNumber));
                ticketBooks.ObserveFilterProperty(nameof(TicketBookDto.EndNumber));
            }
            return ticketBooks;
        }
        set => Set(ref ticketBooks, value);
    }

    #region INotifyStuff
    public event PropertyChangedEventHandler PropertyChanged;
    protected void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Equals(storage, value))
        {
            return;
        }

        storage = value;
        OnPropertyChanged(propertyName);
    }

    protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    #endregion
}

TicketBookDto

public partial class TicketBookDto
{
    public string StartNumber { get; set; }
    public string EndNumber { get; set; }
}

我已经在过滤器中注释掉了我需要的实际逻辑的代码,即只显示那些在“StartNumber”和“EndNumber”属性之间具有搜索编号的列表项。但为简单起见,我使用与 StartNumber 逻辑的简单匹配来找出它不起作用的原因。此外,当我添加一个布尔属性并简单地使用该属性进行过滤时,它可以正常工作,只是不能使用这些字符串属性。

【问题讨论】:

    标签: c# listview filter uwp windows-community-toolkit


    【解决方案1】:

    恐怕Filter不能在TextChanged事件中使用,请参考源代码here

    if (_filter != null)
            {
                for (var index = 0; index < _view.Count; index++)
                {
                    var item = _view.ElementAt(index);
                    if (_filter(item))
                    {
                        continue;
                    }
    
                    RemoveFromView(index, item);
                    index--;
                }
            }
    

    当您在 SerchBox 中输入文本时,如果文本不等于过滤器属性,则项目将为 RemoveFromView。所以它会使下一个输入不起作用。对于这种设计,我们建议您在输入完成后制作提交按钮来过滤数据。

    如果您确实想在TextChanged 中进行过滤,您可以在设置Filter 委托方法之前调用 ViewModel.TicketBooks.Filter = _ =&gt; true; 重置视图,如下所示。

    private void SearchTicketBooks_TextChanged(object sender, TextChangedEventArgs e)
    {
    
        if (ViewModel != null)
        {
            if (string.IsNullOrWhiteSpace(SearchTicketBooksBox.Text))
            {
                ViewModel.TicketBooks.Filter = _ => true;
            }
            else
            {    // reset the filter
                ViewModel.TicketBooks.Filter = _ => true;
                ViewModel.TicketBooks.Filter = x => ((TicketBookDto)x).EndNumber == SearchTicketBooksBox.Text;
    
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-01-13
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      • 2014-06-18
      • 1970-01-01
      相关资源
      最近更新 更多