Reputation: 20494
( First of all I need to clarify that I could manage both C# or VB solution to solve this issue )
Time ago I've asked in this other question how to select an item or range of tiems in a ListBox
without let the control jump to that position, this question now is similar, I just want to perform the same thing of that question but with a telerik RadListControl
.
I have a RadListControl
where I would like to use it to list the runing processes in the system (with a condition that no more than 1 process with the same name), that thing is done and I'm trying to update the list each 2 seconds (firstly determining If exists changes to update the current list),
I'm saving the SelectedItems
property of the control to restore the selected items in the RadListControl
after updating the list and here is the problem, after clearing the items of the control using the Items.Clear
method the Scrollbar moves up to the top of the control and I need to scrolldown to the desired position again and again.
I would like to keep the current position after updating the items in the control, just like Windows TaskManager does for example.
I also tried to set a collection od RadDataItem
as the control DataSource
, but then the Image
property for each item is empty (I don't know why).
Here is a demonstration of the problem:
As you can see, when I run a new process (the window at the left of the gif) the process list is moved to top, the same when I close that process.
I don't know what more to try, here is the relevant part of the code:
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
Upvotes: 1
Views: 1297
Reputation: 7214
The problem is after you clear the list, SelectedItems list does not contain anything. Use instead:
Dim SelectedItems As List(Of String) = New List(Of String)
For Each Item As RadListDataItem In RadListControl_ProcessList.SelectedItems
SelectedItems.Add(Item.Text)
Next
and then you can scroll to any item.
EDIT (I should have explained it in more details. I tend to do that)
What is causing this behavior is the LINQ query you are doing to get the text from the selected items. It doesn't do what you are thinking. eg it is not adding any text in selected items. The query is executed only when you access the SelectedItems:
If SelectedItems.Contains(Item.Text) Then '<- here
at this point the items are being cleared(those which have been associated with SelectedItems) and nothing happens. What you can do to solve the issue is use a static list, as i proposed, or better(not changing your code too much):
Dim SelectedItems As IEnumerable(Of String) =
(From Item As RadListDataItem
In Me.RadListControl_ProcessList.SelectedItems
Select Item.Text).ToArray
both work
valter
Upvotes: 1
Reputation: 3120
If I understand correctly, you want to keep the scroll bar position, once you repopulate the items in the control. If so, the following code can help you achieve it:
int saveValue = radListControl1.ListElement.Scroller.Scrollbar.Value;
//rebind
radListControl1.ListElement.Scroller.Scrollbar.Value = saveValue;
Upvotes: 1