我如何动态地显示每次发生变化时ListBox中的项目计数?

本文关键字:ListBox 变化 项目 何动态 动态 显示 | 更新日期: 2023-09-27 18:14:58

我有一个c#项目,它有一个ListBox作为它的用户界面的一部分。此列表框用于显示多个项目名称。我还可以根据对数据库的查询(所有项目,未完成的,完成的,等等)更改这个ListBox的大小。

我还有一个标签,它将显示ListBox内的结果数量。我希望找到一种方法,在每次列表更改时自动执行此操作,而不是在我更改列表的每一行代码中执行此操作。

我已经尝试使用DataSourceChanged事件,但这提出了一个非常有趣的问题。该事件在ListBox实际用新值填充之前被触发。例如,在程序开始时,我将ListBox的数据源设置为一组100个项目。然后,DataSourceChanged事件被触发,我调用listBox1.Items.Count.ToString()来获取值,它返回0。同样,因为列表框还没有被填充。因此,我将有一个显示0的标签和一个包含100个项目的列表框。

现在,如果我要将其缩小到未完成的项目(例如,将具有50个计数),当事件被触发时,它将返回值100。这是因为自数据源更改以来尚未填充未完成的项目。因此,我将有一个标签,上面写着100,但列表框中只有50个项目。

还有其他事件可以使用吗?DataSourceChanged事件是否有任何参数,我可以查看挂起的数据源以获得计数?或者我真的应该找到代码中每个改变listbox的实例并更新那里的标签吗

我如何动态地显示每次发生变化时ListBox中的项目计数?

您可以使用接口ICollectionView来完成这样的任务,这甚至可以使您保持itemssource的完整(为您的数据库节省一些工作负载,以及大量的混乱)。你还需要为你的itemssource使用ObservableCollection,就像在这里的其他评论中提到的那样。您应该使用绑定、命令和工作,而不是关注WPF中的事件。讨厌的代码背后让老MVVM老手眼睛酸痛,让小猫咪哭;)

尽可能使用过滤器,在完全更改"数据源"时,只需更改stuff集合。请原谅我在这里的命名,我试图让这个例子对你来说尽可能简单。

Xaml:

<Window x:Class="custtest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:custtest="clr-namespace:custtest"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <custtest:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto" MinWidth="100"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ListBox ItemsSource="{Binding Stuffs}" Grid.Row="0" Grid.Column="0"></ListBox>
        <TextBlock  Grid.Row="0" Grid.Column="1" Text="{Binding StuffFilterView.Count}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
        <TextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"  Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ></TextBox>
    </Grid>
</Window>

ViewModel:

下面的代码非常简单,你永远不应该做我在actor中做的事情!这只是为了简单。

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> stuffs;
    private string searchText;
    private ICollectionView stuffFilterView;
    public ICollectionView StuffFilterView
    {
        get { return stuffFilterView; }
        set
        {
            if (Equals(value, stuffFilterView)) return;
            stuffFilterView = value;
            OnPropertyChanged();
        }
    }
    public ObservableCollection<String> Stuffs
    {
        get { return stuffs; }
        set
        {
            if (Equals(value, stuffs)) return;
            stuffs = value;
            OnPropertyChanged();
        }
    }
    public String SearchText
    {
        get { return searchText; }
        set
        {
            if (value == searchText) return;
            searchText = value;
            OnPropertyChanged();
            OnSearchTextChanged();
        }
    }
    private void OnSearchTextChanged()
    {
        StuffFilterView.Refresh(); // Refresheses content in your ICollectionView when text changes            
    }
    public MainViewModel()
    {
        // Bad pie!
        Stuffs = new ObservableCollection<string> {"jall", "b", "c", "d", "blabla"};
        StuffFilterView = CollectionViewSource.GetDefaultView(Stuffs);
        StuffFilterView.Filter = FilterStuff;
    }
    private bool FilterStuff(object obj)
    {
        String str = obj.ToString();
        if (String.IsNullOrEmpty(SearchText))
            return true;
        return str.Contains(SearchText);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    [NotifyPropertyChangedInvocator] // R# remove if you don't have it
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

希望有帮助!

欢呼,Stian