2012-10-09 5 views
0

일부 상품에는 ObservableCollection에 바인딩 된 ListBox이 있습니다. 기본 클래스 또는 상속 된 클래스의 인스턴스가 될 수 있습니다. 3 초 안에 아이템 목록을 업데이트해야합니다. 컬렉션 목록 항목 공급자를 업데이트하려면 새 목록을 다운로드 한 다음 이전 목록과 새 목록을 병합해야합니다. 이전 목록과 새 목록의 항목은 Item.Id 속성을 사용하여 연결됩니다. 문제는 깜박하지 않고 목록 상자에서 항목을 업데이트하고 현재의 선택을 보존하는 방법이다 등깜박임없이 새 인스턴스에서 목록 상자의 항목을 업데이트하는 방법?

  1. list.RemoveAt()를 수행하고 list.InsertAt() 모든 항목을 대체하기 위해 그렇게하는 방법은 두 가지가 있습니다. 또한 업데이트 후 복원하기 전에 CollectionViewSource.DeferRefresh()을 사용하고 현재 선택 사항을 저장하는 것이 유용합니다. 이 방법을 사용하면 툴팁 깜박임과 같은 몇 가지 문제가 발생했습니다.

  2. 다른 방법은 이전 항목의 각 속성을 새 값으로 업데이트하는 것입니다. 그러나 컬렉션에 상속 된 인스턴스가 있기 때문에 일종의 어려운 작업입니다.

이러한 상황을 처리하는 적절한 방법은 무엇입니까? 실제 데이터 업데이트를 효율적으로 구현하는 방법 (업데이트가 새 인스턴스 컬렉션에 다운로드되는 경우)

+0

나는 아이템에 대한 약간의 애니메이션을 사용할 것이라고 생각한다. 페이드 인 (flade out) -> removeAt -> insertAt -> 페이드 인 (fade in)과 같이 깜빡임을 볼 수 없으므로 UX는 가능한 한 매끄럽습니다. – michele

답변

0

PropertyChanged 및 CollectionChanged에 대한 호출 수를 제한해야합니다.

업데이트 재산권과 새로운 값을 확인 == 과거와는 클래스 일치하지 않으면 그렇게 NotifyPropertyChanged

를 호출하지 않으면 그 두 UI 통지와 같이 다음 삽입을 제거하지 않습니다.
새 항목을 지정하기 만하면됩니다. items [4] = newitem.

가상화를 사용하고 있습니까?
항목이 표시되지 않으면 UI가 새로 고침되지 않는다고 생각합니다.

아래를 참조하십시오. 항목이나 항목을 업데이트하는 것 외에 다른 UI가 깜박 거리지 않습니다. 나는 당신이 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; } 
    } 
} 
0

구현 방법에 관계없이 항상 전체 목록 상자를 새로 고칩니다. listbox의 다른 메소드에서는 문제가 아니지만 listbox가 목록의 항목을 칠하는 방법은 다릅니다.

목록 상자를 서브 클래스 화하고 onpaint를 재정의해야 할 수도 있습니다.보다 효율적인 코드로 작성하면 깜박임없이 사용할 수 있습니다.

과거에 ListView에서 수행했습니다. http://www.codeproject.com/Articles/3617/Flicker-free-ListView-in-NET-Part-2 이 코드를 사용하십시오.

플리커가없는 목록 상자를 개발할 때 도움이 될 수 있습니다.

+0

단일 항목을 업데이트해도 전체 목록 상자가 새로 고쳐지지 않습니다. – Paparazzi

관련 문제