ElektroStudios
ElektroStudios

Reputation: 20494

Telerik, Updating RadListControl items issue

( 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:

enter image description here

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

Answers (2)

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

checho
checho

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

Related Questions