(Прежде всего, мне нужно уточнить, что я могу управлять решением С# или VB для решения этой проблемы)
Время назад я задал в этом другом вопросе, как выбрать элемент или диапазон тимсов в ListBox
не позволяя элементу управления перейти к этой позиции, теперь этот вопрос аналогичен, я просто хочу выполнить то же самое в этом вопросе, но с telerik RadListControl
.
У меня есть RadListControl
где я хотел бы использовать его для отображения процессов запуска в системе (с условием, что не более одного процесса с тем же именем), эта вещь выполняется, и я пытаюсь обновить список каждые 2 секунд (во-первых, определение Если существуют изменения для обновления текущего списка), я RadListControl
свойство SelectedItems
элемента управления для восстановления выбранных элементов в RadListControl
после обновления списка, и вот проблема, после очистки элементов элемента управления, используя Метод Items.Clear
прокрутки перемещается вверху элемента управления, и мне нужно снова и снова прокручивать ее до нужной позиции. Я бы хотел сохранить текущую позицию после обновления элементов в элементе управления, как, например, Windows TaskManager.
Я также попытался установить коллекцию RadDataItem
качестве RadDataItem
управления DataSource
, но тогда свойство Image
для каждого элемента пуст (я не знаю почему).
Вот демонстрация проблемы:
Как вы можете видеть, когда я запускаю новый процесс (окно слева от gif), список процессов перемещается в начало, то же самое, когда я закрываю этот процесс.
Я не знаю, что еще нужно попробовать, вот соответствующая часть кода:
Private Sub Timer_RefreshProcessList_Tick(ByVal sender As Object, ByVal e As EventArgs) _
Handles Timer_RefreshProcessList.Tick
' Processes that shouldn't be listed.
Dim BlackListedProcesses As String() =
{
My.Application.Info.AssemblyName,
"Idle",
"System",
"audiodg"
}
' Get the runing processes.
Dim Processes As Process() = Process.GetProcesses
' Filter the processes by its name
' then set the RadListDataItem items containing the names and the process icons.
Dim ProcessItems As IEnumerable(Of RadListDataItem) =
(From proc As Process In Processes
Where Not BlackListedProcesses.Contains(proc.ProcessName)
Order By proc.ProcessName Ascending).
GroupBy(Function(proc As Process) proc.ProcessName).
Select(Function(procs As IGrouping(Of String, Process))
If Not procs.First.HasExited Then
Try
Return New RadListDataItem With
{
.Active = False,
.Text = String.Format("{0}.exe", procs.First.ProcessName),
.Image = ResizeImage(Icon.ExtractAssociatedIcon(procs.First.MainModule.FileName).ToBitmap,
Width:=16, Height:=16)
}
Catch ex As Exception
Return Nothing
End Try
Else
Return Nothing
End If
End Function)
' If the RadListControl does not contain any item then...
If Me.RadListControl_ProcessList.Items.Count = 0 Then
With Me.RadListControl_ProcessList
.BeginUpdate()
.Items.AddRange(ProcessItems) ' Add the RadListDataItems for first time.
.EndUpdate()
End With
Exit Sub
End If
' If RadListDataItems count is not equal than the runing process list count then...
If Me.RadListControl_ProcessList.Items.Count <> ProcessItems.Count Then
' Save the current selected items.
Dim SelectedItems As IEnumerable(Of String) =
From Item As RadListDataItem
In Me.RadListControl_ProcessList.SelectedItems
Select Item.Text
' For Each ctrl As RadListDataItem In ProcessItems
' ctrl.Dispose()
' Next
With Me.RadListControl_ProcessList
' .AutoScroll = False
' .SuspendSelectionEvents = True
' .SuspendItemsChangeEvents = True
' .SuspendLayout()
' .BeginUpdate()
.Items.Clear() ' Clear the current RadListDataItems
.Items.AddRange(ProcessItems) ' Add the new RadListDataItems.
' .EndUpdate()
' .ResumeLayout()
End With
' Restore the selected item(s).
For Each Item As RadListDataItem In Me.RadListControl_ProcessList.Items
If SelectedItems.Contains(Item.Text) Then
Item.Selected = True
Item.Active = True
With Me.RadListControl_ProcessList
' .ScrollToItem(Item)
' .ListElement.ScrollToItem(Item)
' .ListElement.ScrollToActiveItem()
End With
End If
Next Item
With Me.RadListControl_ProcessList
' .AutoScroll = True
' .SuspendSelectionEvents = False
' .SuspendItemsChangeEvents = False
End With
End If
End Sub
Проблема заключается в том, что после удаления списка список SelectedItems не содержит ничего. Используйте вместо этого:
Dim SelectedItems As List(Of String) = New List(Of String)
For Each Item As RadListDataItem In RadListControl_ProcessList.SelectedItems
SelectedItems.Add(Item.Text)
Next
и затем вы можете прокручивать любой предмет.
EDIT (я должен был объяснить это более подробно. Я, как правило, это делаю)
Это вызывает запрос LINQ, чтобы получить текст из выбранных элементов. Он не делает то, что вы думаете. например, он не добавляет текст в выбранные элементы. Запрос выполняется только при доступе к SelectedItems:
If SelectedItems.Contains(Item.Text) Then '<- here
в этот момент элементы очищаются (те, которые были связаны с SelectedItems), и ничего не происходит. Что вы можете сделать для решения проблемы, это использовать статический список, как я предложил, или лучше (не слишком сильно меняя свой код):
Dim SelectedItems As IEnumerable(Of String) =
(From Item As RadListDataItem
In Me.RadListControl_ProcessList.SelectedItems
Select Item.Text).ToArray
оба работают
Valter
Если я правильно понимаю, вы хотите сохранить положение полосы прокрутки, как только вы заселяете элементы в элементе управления. Если это так, следующий код может помочь вам в этом:
int saveValue = radListControl1.ListElement.Scroller.Scrollbar.Value;
//rebind
radListControl1.ListElement.Scroller.Scrollbar.Value = saveValue;
RadControl.SelectedItems
, но только на это, указывая только на его элементы, поэтому, как только я очистил списокControl.SelectedItem
мой список также начинается пустым, потому что есть какие-либо элементы, на которые я могу указать, я я прав ?, чего я не понимаю, так это почему я делаю это, потому что это решает проблему, я не делал то же самое, но использую Linq?, извините за мой английский и спасибо за ваш ответ!