2015-10-21 4 views
2

Я пытаюсь создать GridView с номером строки и, чтобы пользовательские кнопки вверх/вниз изменили порядок строк. Многие сообщения предлагают использовать AlternationIndex (например, here) и что почти отлично работает, и он обрабатывает, когда пользователь нажимает кнопки вверх/вниз, чтобы изменить порядок строк. Но AlternationIndex терпит неудачу, когда вы перемещаете элемент в первую позицию - в этот момент он должен показывать 0, но вместо этого он обертывается до последнего значения в AlternationCount.WPF AlternationIndex обертывается при перемещении элементов вверху списка

Пример:

<ListView AlternationCount="1000" Name="_stuff" Grid.Row="0"> 
       <ListView.View> 
        <GridView> 
         <GridViewColumn 
           Header="Alit" Width="30" 
           DisplayMemberBinding="{Binding (ItemsControl.AlternationIndex), 
           RelativeSource={RelativeSource AncestorType=ListViewItem}}" /> 

         <GridViewColumn Header="ColumnName" DisplayMemberBinding="{Binding}" Width="240"/> 
        </GridView> 
       </ListView.View> 
      </ListView> 

, а затем мой код, за это:

ObservableCollection<string> data = new ObservableCollection<string>() { "First", "Second", "Third", "Forth", "Last" }; 

public MainWindow() 
{ 
     InitializeComponent(); 
     _stuff.ItemsSource = data; 
    } 

    private void UpDownButton_Click(object sender, RoutedEventArgs e) 
    { 
     //User wants to change the order -- remove the item from the observable 
     //collection and reinsert it at the new position. 
     data.Remove("Last"); //First remove, then re-insert. 

     //If you move the last item to *middle* of list, it works fine and the index 
     //is correct. (All other items are pushed down by 1, like you'd expect.) 
     //But move to the *top* of the list and the new index is 999? 

     //THIS WOULD WORK FINE AND ALL INDEXES ARE CORRECT 
     // data.Insert(3, "Last"); //Insert to middle of list 

     //But this gives an index of 999???? Seems to be wrapping 
     //around to the last AlternationCount. But why? 
     data.Insert(0, "Last"); //insert to top of list 
    } 

Любых идеи, как я могу сделать alternationIndex этого нового элемента на вершине быть 0 вместо 999?

ответ

1

Я думаю, что это ошибка. Для него неприемлемо вести себя так. Как-то AltenrationIndex настроен неправильно, вы можете найти исходный код об этом, но, откровенно говоря, это не очень легко понять. Существует несколько алгоритмов, которые включают в себя механизм виртуализации, а также модель, которую они реализуют. Вот исходный код, который, я думаю, может включать обновление до AlternationIndex, метод SetAlternationIndex. Это называется в некоторых обратных вызовов, таких как, когда AlternationCount изменяется, элемент удаляется, ...

Некоторые жесткие для понимания концепций здесь ItemBlock и offset, а также GeneratorDirection. Вот почему мне сложно понять код там.

Я отправляю этот ответ, потому что я нашел простое решение, которое работает, хотя я не уверен, что с ним связана проблема с производительностью, но я уверен, что он должен быть приемлемым.

AlternationIndex должен быть в порядке, если контейнеры товаров повторно сгенерированы. Поскольку в режиме виртуализации количество контейнеров элементов равно количеству видимых элементов, поэтому я думаю, что это не приводит к проблеме производительности. ItemContainerGenerator реализует интерфейс IItemContainerGenerator, который имеет метод под названием RemoveAll. Используя этот метод, все реализованные (сгенерированные) контейнеры элементов будут удалены, и они будут автоматически сгенерированы снова, в результате чего AlternationIndex будет установлен в правильном порядке.

Кроме того, как вы сказали, проблема возникает, только когда элемент вставлен в первый индекс. Таким образом, мы просто должны использовать этот трюк, только для этого конкретного случая:

private void UpDownButton_Click(object sender, RoutedEventArgs e) 
{ 
    //before changing any item at index 0 such as by inserting 
    //some new one or even use the method Move(... , 0),  
    //We need to clear all the realized item containers 
    var cg = _stuff.ItemContainerGenerator as IItemContainerGenerator; 
    cg.RemoveAll(); 
    //now just proceed the code 
    //we can in fact use this instead data.Move(data.Count - 1, 0); 
    data.Remove("Last"); 
    data.Insert(0, "Last");  
} 

Вот еще один довольно решение с использованием ICollectionView.Refresh() метода. Вам просто нужно обновить его (но, конечно, должно применяться только тогда, когда возникает эта проблема):

private void UpDownButton_Click(object sender, RoutedEventArgs e) 
{  
    //we can in fact use this instead data.Move(data.Count - 1, 0); 
    data.Remove("Last"); 
    data.Insert(0, "Last");  
    CollectionViewSource.GetDefaultView(data).Refresh(); 
} 
+0

Вашего первое предложение не работает для меня (строки появились дублируются каждый раз), но второе предложение вызова ICollectionview.Refresh(), похоже, делает трюк. Благодаря! – user2543623

Смежные вопросы