wpf 如何从新示例更新列表框中的项目而不 Flink ?

pjngdqdw  于 2022-12-14  发布在  Flink
关注(0)|答案(3)|浏览(105)

我有一个绑定到ObservableCollectionListBox,其中包含一些项。它们可能是基类或某些继承类的示例。我需要在3秒内更新一次项列表。若要更新集合列表,项提供程序将下载新列表,然后我需要合并新旧列表。新旧列表中的项使用Item.Id属性关联。问题是如何更新列表框中的项目而不 Flink ,并保持当前选择等。
有两种方法可以做到这一点
1.用list.RemoveAt()list.InsertAt()来替换所有的项目。同样,使用CollectionViewSource.DeferRefresh()并在更新前保存当前选择并在更新后恢复也很有用。用这种方法我遇到了一些问题,比如工具提示 Flink 等。
1.另一种方法是用新值更新旧项的每个属性。但这有点困难,因为集合中有一些继承的示例。
处理这种情况的正确方法是什么?如何有效地实现实时数据更新(当更新在新示例集合中下载时)?

vojdkbi0

vojdkbi01#

无论你如何实现它,它总是会刷新整个列表框。这不是不同的列表框方法的问题,而是列表框如何绘制列表中的项目。
您可能需要创建列表框的子类,覆盖其onpaint even,并编写更有效的代码,使其无 Flink 。
我已经这样做了在过去的ListView http://www.codeproject.com/Articles/3617/Flicker-free-ListView-in-NET-Part-2使用此代码。
也许这可能有助于开发一个无 Flink 的列表框也。

jqjz2hbq

jqjz2hbq2#

需要限制对PropertyChanged和CollectionChanged的调用次数。
更新属性并检查新值是否==旧值,如果是,则不调用NotifyPropertyChanged
如果不是类匹配,则不要删除插入,因为这是两个UI通知。
只需分配新项。items[4] = newitem。
您是否正在使用虚拟化。
如果该项目未显示,则UI不会刷新。
请看下面。我没有得到任何UI Flink 以外的项目或项目更新。我怀疑你没有正确地利用PropertyChanged。

<Window x:Class="ListViewUpdate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        DataContext="{Binding RelativeSource={RelativeSource self}}"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <Button Content="Add10000" Click="Button_Click"/>
            <Button Content="UpdateFirst" Click="Button_Click_1"/>
            <Button Content="UpdateLast" Click="Button_Click_2"/>
            <Button Content="ReplaceFirst" Click="Button_Click_3" />
            <Button Content="UpdateAll" Click="Button_Click_4"/>
        </StackPanel>
        <ListView Grid.Row="1" ItemsSource="{Binding Path=Persons}" DisplayMemberPath="Name" />
    </Grid>
</Window>

namespace ListViewUpdate
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ObservableCollection<Person> persons = new ObservableCollection<Person>();
        public MainWindow()
        {
            InitializeComponent();
        }
        public ObservableCollection<Person> Persons { get { return persons; } }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            for (UInt16 i = 0; i < 10000; i++)
            {
                Persons.Add(new Person(Guid.NewGuid().ToString()));
            }
            System.Diagnostics.Debug.WriteLine("");
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (Persons.Count == 0) return;
            for (UInt16 i = 0; i < UInt16.MaxValue; i++)
            {
                Persons[0].Name = Guid.NewGuid().ToString();
            }
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            if (Persons.Count == 0) return;
            int last = Persons.Count - 1;
            for (UInt16 i = 0; i < UInt16.MaxValue; i++)
            {
                Persons[last].Name = Guid.NewGuid().ToString();
            }
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            if (Persons.Count == 0) return;
            for (UInt16 i = 0; i < UInt16.MaxValue; i++)
            {
                Persons[0] = new Person(Guid.NewGuid().ToString());
            }
        }

        private void Button_Click_4(object sender, RoutedEventArgs e)
        {
            foreach (Person p in Persons) p.Name = Guid.NewGuid().ToString();
        }
    }
    public class Person: INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        private string name;
        public string Name 
        {
            get { return name; }
            set
            {
                if (name == value) return;
                name = value;
                NotifyPropertyChanged("Name");
            }
        }
        public Person(string name) { Name = name; }
    }
}
shstlldc

shstlldc3#

我遇到了同样的问题,我发现我可以像这样使用BeginUpdate()EndUpdate()方法:

_listView.BeginUpdate();
_listView.Items.Clear();
_listView.Items.AddRange(newItems);
_listView.EndUpdate();

它根本没有消除轻弹,但它变得好多了,我的眼睛不疼了。

相关问题