Эта проблема проста.
RecyclerView
повторно использует держателей, каждый раз вызывая bind для обновления данных в них.
Поскольку вы создаете CountDownTimer
каждый раз, когда какие-либо данные связаны, у вас будет несколько таймеров, обновляющих одно и то же ViewHolder
.
Лучше всего было бы cancel
это связать данные (если они начались) и перенести на желаемую продолжительность.
blockquote>public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { ... if (holder.timer != null) { holder.timer.cancel(); } holder.timer = new CountDownTimer(expiryTime, 500) { ... }.start(); } public static class ResturantDashboardViewHolder extends RecyclerView.ViewHolder { ... CountDownTimer timer; public FeedViewHolder(View itemView) { ... } }
Таким образом, вы отмените любой текущий экземпляр таймера для этого
ViewHolder
до запуска другого таймера.
Я нашел способ сделать эту работу. Я выломаю его в разделы...
List<myType> myList = new List<myType>(someCapacity);
.
...populate the list with query from database...
.
DataGridTableStyle myDataGridTableStyle = new DatGridtTableStyle();
DataGridTextBoxColumn colA = new DataGridTextBoxColumn();
DataGridTextBoxColumn colB = new DataGridTextBoxColumn();
DataGridTextBoxColumn colC = new DataGridTextBoxColumn();
colA.MappingName = "FieldA";
colA.HeaderText = "Field A";
colA.Width = 50; // or whatever;
colB.MappingName = "FieldB";
.
... etc. (lather, rinse, repeat for each column I want)
.
myDataGridTableStyle.GridColumnStyles.Add(colA);
myDataGridTableStyle.GridColumnStyles.Add(colB);
myDataGridTableStyle.GridColumnStyles.Add(colC);
var query = from i in myList
select new
{
i.FieldA,
i.FieldB,
i.FieldC
};
myBindingSource.DataSource = query.ToList(); // Thanks Marc Gravell
// wasn't sure what else to pass in here, but null worked.
myDataGridTableStyle.MappingName = myBindingSource.GetListName(null);
myDataGrid.TableStyles.Clear(); // Recommended on MSDN in the code examples.
myDataGrid.TablesStyles.Add(myDataGridTableStyle);
myDataGrid.DataSource = myBindingSource;
Так в основном, DataGridTableStyle. MappingName должен знать, на какой объект он отображается. Так как мой объект является анонимным типом (созданный с Linq), я не знаю то, что это до времени выполнения. После того, как я свяжу список анонимного типа к обязательному источнику, я могу использовать BindingSource. GetListName (пустой указатель) для получения строкового представления анонимного типа.
Одна вещь отметить. Если я просто связал myList (который является типом "myType"), непосредственно к обязательному источнику, я, возможно, просто использовал строку "myType" в качестве значения для DataGridTableStyle. MappingName.
Надо надеяться, это полезно для других людей!
Возвраты запроса IEnumerable<T>
для некоторых T
, но самые обязательные источники (кроме ASP.NET) требуют IList
(такие как любой IList<T>
реализация) - пытаются добавить .ToList()
- т.е.
myBindingSource.DataSource = query.ToList();
A BindingList<T>
мог бы работать еще лучше (если это поддерживается в CF 3.5), так как это имеет лучшую поддержку некоторых общих обязательных сценариев; если Вам нужно это (и принятие BindingList<T>
существует на CF 3.5), можно добавить дополнительный метод:
static BindingList<T> ToBindingList<T>(this IEnumerable<T> data)
{
return new BindingList<T>(new List<T>(data));
}
затем вызов:
myBindingSource.DataSource = query.ToBindingList();
Для полноты, альтернативы IList
IListSource
(или даже Type
для сценариев просто-метаданных), который является почему DataSource
обычно вводится как object
; если бы это не было для этой проблемы, компилятор, вероятно, смог бы сказать Вам проблему (т.е. если DataSource
был определен как IList
).