WPF中刷新ListBox的简单方法?

9
我创建了一个简单的表格,用于插入/更新/删除Northwind客户的值。一切都运行良好,但是为了查看结果,我必须关闭并重新打开它。我的表格看起来像这样:enter image description here
我已经搜索了数十篇关于如何刷新ListBox的文章,但所有这些文章都使用接口实现或使用DataSets等我从未听说过且无法实现的东西。这是一个非常简单的项目,使用简单的程序。有没有一种简单的方法可以在不添加太多代码的情况下刷新客户列表?

2
你是否正在使用 ObservableCollection 并且你的模型实现了 INotifyPropertyChanged 接口,这两个条件将会在任何更改时自动更新 ListBox,无需显式刷新列表。 - sa_ddam213
1
在所有地方(添加/删除)调用listBoxYourName.Items.Refresh()对我有用。即使集合绑定到ItemsSource。这是一个奇怪但真实的故事,朋友们。 - SmartK8
4个回答

32
简单的答案是:myListBox.Items.Refresh();

4
这是问题的答案。 - MarcioAB

13

您是否正在使用 ObservableCollection,并且您的模型实现了 INotifyPropertyChanged 接口?这两件事情将在任何更改时自动更新 ListBox。无需明确刷新列表。

以下是使用 ObservableCollectionINotifyPropertyChanged 的一个小例子,显然您将从您的 SQL 数据库中填充 ObservableCollection。

窗口:

public partial class MainWindow : Window,  INotifyPropertyChanged
{
    private ObservableCollection<MyModel> _list = new ObservableCollection<MyModel>();
    private MyModel _selectedModel;

    public MainWindow()
    {
        InitializeComponent();
        List.Add(new MyModel { Name = "James", CompanyName = "StackOverflow"});
        List.Add(new MyModel { Name = "Adam", CompanyName = "StackOverflow" });
        List.Add(new MyModel { Name = "Chris", CompanyName = "StackOverflow" });
        List.Add(new MyModel { Name = "Steve", CompanyName = "StackOverflow" });
        List.Add(new MyModel { Name = "Brent", CompanyName = "StackOverflow" });
    }

    public ObservableCollection<MyModel> List 
    {
        get { return _list; }
        set { _list = value; }
    }

    public MyModel SelectedModel
    {
        get { return _selectedModel; }
        set { _selectedModel = value; NotifyPropertyChanged("SelectedModel"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

Xaml

<Window x:Class="WpfApplication11.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Name="UI">
    <Grid>
        <ListBox ItemsSource="{Binding ElementName=UI, Path=List}" SelectedItem="{Binding ElementName=UI, Path=SelectedModel}" Margin="0,0,200,0" DisplayMemberPath="DisplayMember" SelectedIndex="0" />
        <StackPanel HorizontalAlignment="Left" Height="100" Margin="322,10,0,0" VerticalAlignment="Top" Width="185">
            <TextBlock Text="Name" />
            <TextBox Height="23" TextWrapping="Wrap" Text="{Binding ElementName=UI, Path=SelectedModel.Name, UpdateSourceTrigger=PropertyChanged}" />
            <TextBlock Text="Company Name" />
            <TextBox Height="23" TextWrapping="Wrap" Text="{Binding ElementName=UI, Path=SelectedModel.CompanyName, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
    </Grid>
</Window>

模型

public class MyModel : INotifyPropertyChanged
{
    private string _name;
    private string _companyName;

    public string Name
    {
        get { return _name; }
        set { _name = value; NotifyPropertyChanged("Name"); }
    }

    public string CompanyName
    {
        get { return _companyName; }
        set { _companyName = value; NotifyPropertyChanged("CompanyName"); }
    }

    public string DisplayMember
    {
        get { return string.Format("{0} ({1})", Name, CompanyName); }

    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
            PropertyChanged(this, new PropertyChangedEventArgs("DisplayMember"));
        }
    }
}

在这种情况下,对属性的任何编辑都会立即更新您的列表,并且当添加/删除新项目时也会进行更新。

输入图片描述


非常感谢,节省了很多时间:D - Mugiwara

3

试试调用ListBox.UpdateLayout怎么样?

当然,您还需要更新特定的项,以便从ToString方法返回更新后的字符串。

更新:我认为在调用ListBox.UpdateLayout之前您还需要调用ListBox.InvalidateArrange。


我需要更新哪些项目以及如何更新? 另外,这些代码应该放在哪里?在Insert/Update/Delete方法之后吗? - Fengson
仍然没有任何变化... :/ - Fengson
我认为listbox本身有一个刷新选项。就像listbox1.refresh(),它可以做同样的事情。 - Mullaly
我的意思是您之前添加到列表框中的项目,它们很可能是覆盖了Object.ToString方法的对象,不是吗? - user1610015
1
你可以尝试清空列表框并重新从数据库中绘制。 - Mullaly

0

使用INotifyPropertyChanged是最好的方法,刷新整个列表不是一个好主意。
主入口:

public partial class MainWindow : Window
{
    private BindingList<FoodModel> foodList = new BindingList<FoodModel>();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button1_Click(object sender, RoutedEventArgs e)
    {
        foodList.Add(new FoodModel { foodName = "apple1" });
        foodList.Add(new FoodModel { foodName = "apple2" });
        foodList.Add(new FoodModel { foodName = "apple3" });
        FoodListBox.ItemsSource = foodList;
    }

    private void Button2_Click(object sender, RoutedEventArgs e)
    {
        foodList[0].foodName = "orange";
    }

    private void RefreshButton_Click(object sender, RoutedEventArgs e)
    {
        FoodListBox.Items.Refresh();
    }
}

模型:

public class FoodModel: INotifyPropertyChanged
{
    private string _foodName;

    public string foodName
    {
        get { return _foodName; }
        set
        {
            if (_foodName != value)
            {
                _foodName = value;
                PropertyChanged(this, new PropertyChangedEventArgs("foodName"));
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

XAML:

 <ListBox HorizontalAlignment="Center" Name="FoodListBox" VerticalAlignment="Top" Width="194" Height="150">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding foodName}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接