RadListControl and RadGridView FIlters

9 posts, 2 answers
  1. Dean Allan
    Dean Allan avatar
    12 posts
    Member since:
    Jan 2010

    Posted 13 Feb 2011 Link to this post

    Hello,

    I was hoping someone could shed some light on this situation.

    I have a RadPageView with a RadListControl inside.  The list control is populated from a sql table that contains potential 'status' setting for a recordset that is filling a RadGridView also on the same page.  I have the list control MultiSelect set to 'Simple'. The idea is a fast, multi-select filter for the radgrid.

    So as with most issues, 90% works great.  Using RadListControl1.SelectedIndexChanged as my event handler I am able to create a filter for the radgrid using OR to allow filtering for multiple status at one time.   If the user clicks status 'a' then status 'b' then status 'c' the Radgrid filters and only shows 'A',then adds 'B',then 'C'.  Perfect! (status LIKE 'A' or status LIKE 'B' or status LIKE 'C' is  the expression I end up with, again perfect)

    Here is where is problem lies.  When a user un-selects items in the RadListControl in reverse order (Add, A,B,C then Remove C,B,A) things seem to work, the event handler fires properly.  However, if the user un-selects items in any other order the event wont fire (Add A,B,C  then unselect A,B,C).  I'm guessing this is by design.  Although I have a loop with a message box showing the RadLIstControl items each time the event fires (for debugging).  I don't know if this might have some unseen effect on the control.

    So I am wondering, is there a solution for this situation, either using the RadListControl (it's fast) or would there be a better method, I just can't seem to get my head around this one.  My code is in VB if that matters.

    Thanks in advance!

    Dean.

  2. Answer
    Richard Slade
    Richard Slade avatar
    3000 posts
    Member since:
    May 2009

    Posted 13 Feb 2011 Link to this post

    Hi Dean,

    Here's another way. Subscribe to the RadPropertyChanged for each item and capture the selected propert

    For Each item As RadListDataItem In Me.RadListControl1.Items
        AddHandler item.RadPropertyChanged, AddressOf RadListControl_RadPropertyChanged
    Next

    Private Sub RadListControl_RadPropertyChanged(ByVal sender As Object, ByVal e As RadPropertyChangedEventArgs)
        If e.Property.Name = "Selected" Then
            Dim item As RadListDataItem = CType(sender, RadListDataItem)
            MessageBox.Show(item.Text & " is selected: " & item.Selected.ToString())
        End If
    End Sub

    Hope that helps
    Richard
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Dean Allan
    Dean Allan avatar
    12 posts
    Member since:
    Jan 2010

    Posted 15 Feb 2011 Link to this post

    Hi Richard,

    Thanks for the input.

    Just so I know, based on what I see, the first snippet manually adds an event handler to each item in the ListControl on the form load.  The second is the Sub that gets called. I notice there isn't a 'handles' in the sub, I guess this isn't necessary since the event handler is called directly?

    So far your suggestion is working well.  I noticed the selecteditems.count() isn't accurate at the time this event fires though;  for example, I show a count of 2 when I have one selected.  I can figure out a workaround but is there another method related to your solution to iterate the selected collection?

    Thanks again! 

    Dean.

    Here is an example of the code I am working on. I rem'ed out the the loop that wasn't working for debugging.  I tried both 1 and 0 for the loop.
    Private Sub RadListControl_RadPropertyChanged(ByVal sender As Object, ByVal e As RadPropertyChangedEventArgs)
           If e.Property.Name = "Selected" Then
               'Dim x As Integer
               Dim item As RadListDataItem = CType(sender, RadListDataItem)
               ' MessageBox.Show(item.Text & " is selected: " & item.Selected.ToString())
               Me.RadGridView1.FilterDescriptors.Clear()
               Me.RadGridView1.FilterDescriptors.LogicalOperator = FilterLogicalOperator.Or
     
               ' For x = 1 To Me.RadListControl1.SelectedItems.Count()
               MsgBox(RadListControl1.SelectedItems.Count())
               Me.RadGridView1.FilterDescriptors.Add("status", FilterExpression.BinaryOperation.[OR], item.Text)
               ' Next
     
           End If
       End Sub

  5. Richard Slade
    Richard Slade avatar
    3000 posts
    Member since:
    May 2009

    Posted 15 Feb 2011 Link to this post

    Hi Dean,

    No, you don't need a Handler for those that have had an event handler manually added.
    The reason that the items count seems incorrect on the de-selection is because when you message out the selection the prioperty has changed but appear still to be selected.
    You can get over this with the following
    Declare a private int
    Private m_ItemsCount As Integer = 0

    Private Sub RadListControl_RadPropertyChanged(ByVal sender As Object, ByVal e As RadPropertyChangedEventArgs)
        If e.Property.Name = "Selected" Then
            If CType(sender, RadListDataItem).Selected Then
                m_ItemsCount = m_ItemsCount + 1
            Else
                m_ItemsCount = m_ItemsCount - 1
            End If
            MessageBox.Show(m_ItemsCount.ToString())
        End If
    End Sub

    Hope thast helps but let me know if you need anything else
    Richard
  6. Dean Allan
    Dean Allan avatar
    12 posts
    Member since:
    Jan 2010

    Posted 15 Feb 2011 Link to this post

    Hey Richard,

    That did make the count correct but I still keep hitting a brick wall.

    Let me ask this; What is the best way to add/remove a filter to a datagrid using a ListControl with multiple simple select?  

    Thanks again for the assistance!

    Dean.

    This is what I have so far but it seems the event is called several times and i am at a loss.
    Private Sub RadListControl_RadPropertyChanged(ByVal sender As Object, ByVal e As RadPropertyChangedEventArgs)
        Me.RadGridView1.FilterDescriptors.Clear() ' i assumed this sub was only called once per click. This clears the filter and rebuilds it's rather than pop items on and off.
        If CType(sender, RadListDataItem).Selected Then
            Dim item As RadListDataItem = CType(sender, RadListDataItem)
            Me.RadGridView1.FilterDescriptors.LogicalOperator = FilterLogicalOperator.Or
            Me.RadGridView1.FilterDescriptors.Add("status", FilterExpression.BinaryOperation.[OR], Me.RadListControl1.SelectedItems.Item(x).ToString)
        End If
    End Sub



  7. Answer
    Richard Slade
    Richard Slade avatar
    3000 posts
    Member since:
    May 2009

    Posted 15 Feb 2011 Link to this post

    Hi Dean,

    Ok, I've put togeether a small sample for you. I think in this case it's best to use Custom Filtering and I've also changed slightly the handler to pick up the click event rather than the RadPropertyChanged. All seems to work fine but let me know if you have any questions

    Designer File
    <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
    Partial Class Form1
        Inherits System.Windows.Forms.Form
      
        'Form overrides dispose to clean up the component list.
        <System.Diagnostics.DebuggerNonUserCode()> _
        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            Try
                If disposing AndAlso components IsNot Nothing Then
                    components.Dispose()
                End If
            Finally
                MyBase.Dispose(disposing)
            End Try
        End Sub
      
        'Required by the Windows Form Designer
        Private components As System.ComponentModel.IContainer
      
        'NOTE: The following procedure is required by the Windows Form Designer
        'It can be modified using the Windows Form Designer.  
        'Do not modify it using the code editor.
        <System.Diagnostics.DebuggerStepThrough()> _
        Private Sub InitializeComponent()
            Dim RadListDataItem1 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
            Dim RadListDataItem2 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
            Dim RadListDataItem3 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
            Dim RadListDataItem4 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
            Dim RadListDataItem5 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
            Me.RadListControl1 = New Telerik.WinControls.UI.RadListControl()
            Me.RadGridView1 = New Telerik.WinControls.UI.RadGridView()
            CType(Me.RadListControl1, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me.RadGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.SuspendLayout()
            '
            'RadListControl1
            '
            Me.RadListControl1.CaseSensitiveSort = True
            Me.RadListControl1.Dock = System.Windows.Forms.DockStyle.Left
            RadListDataItem1.Text = "Available"
            RadListDataItem1.TextWrap = True
            RadListDataItem2.Text = "Unavailable"
            RadListDataItem2.TextWrap = True
            RadListDataItem3.Text = "Busy"
            RadListDataItem3.TextWrap = True
            RadListDataItem4.Text = "Meeting"
            RadListDataItem4.TextWrap = True
            RadListDataItem5.Text = "Holiday"
            RadListDataItem5.TextWrap = True
            Me.RadListControl1.Items.Add(RadListDataItem1)
            Me.RadListControl1.Items.Add(RadListDataItem2)
            Me.RadListControl1.Items.Add(RadListDataItem3)
            Me.RadListControl1.Items.Add(RadListDataItem4)
            Me.RadListControl1.Items.Add(RadListDataItem5)
            Me.RadListControl1.Location = New System.Drawing.Point(0, 0)
            Me.RadListControl1.Name = "RadListControl1"
            Me.RadListControl1.Size = New System.Drawing.Size(120, 282)
            Me.RadListControl1.TabIndex = 0
            Me.RadListControl1.Text = "RadListControl1"
            '
            'RadGridView1
            '
            Me.RadGridView1.Dock = System.Windows.Forms.DockStyle.Fill
            Me.RadGridView1.Location = New System.Drawing.Point(120, 0)
            Me.RadGridView1.Name = "RadGridView1"
            Me.RadGridView1.Size = New System.Drawing.Size(204, 282)
            Me.RadGridView1.TabIndex = 0
            Me.RadGridView1.Text = "RadGridView1"
            '
            'Form1
            '
            Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
            Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
            Me.ClientSize = New System.Drawing.Size(324, 282)
            Me.Controls.Add(Me.RadGridView1)
            Me.Controls.Add(Me.RadListControl1)
            Me.Name = "Form1"
            Me.Text = "Form1"
            CType(Me.RadListControl1, System.ComponentModel.ISupportInitialize).EndInit()
            CType(Me.RadGridView1, System.ComponentModel.ISupportInitialize).EndInit()
            Me.ResumeLayout(False)
      
        End Sub
        Friend WithEvents RadListControl1 As Telerik.WinControls.UI.RadListControl
        Friend WithEvents RadGridView1 As Telerik.WinControls.UI.RadGridView
      
    End Class

    Form1.vb
    Imports System.ComponentModel
    Imports Telerik.WinControls.UI
    Imports Telerik.WinControls
      
    Public Class Form1
      
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim list As New BindingList(Of MyStatus)
            list.Add(New MyStatus("Richard", "Available"))
            list.Add(New MyStatus("Bob", "Holiday"))
            list.Add(New MyStatus("Chris", "Holiday"))
            list.Add(New MyStatus("Stew", "Unavailable"))
            list.Add(New MyStatus("Pete", "Busy"))
            list.Add(New MyStatus("Ester", "Busy"))
            list.Add(New MyStatus("Harriet", "Meeting"))
            list.Add(New MyStatus("Leisl", "Available"))
            list.Add(New MyStatus("Tonia", "Busy"))
      
            Me.RadGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill
            Me.RadGridView1.EnableFiltering = True
            Me.RadGridView1.ShowFilteringRow = False
            Me.RadGridView1.EnableCustomFiltering = True
            Me.RadListControl1.SelectionMode = SelectionMode.MultiSimple
            Me.RadGridView1.DataSource = list
      
      
            For Each item As RadListDataItem In Me.RadListControl1.Items
                AddHandler item.VisualItem.Click, AddressOf RadListControl1_ItemClick
            Next
        End Sub
      
        Private Sub RadListControl1_ItemClick(ByVal sender As Object, ByVal e As EventArgs)
            Me.RadGridView1.MasterTemplate.Refresh()
        End Sub
      
        Private Sub RadGridView1_CustomFiltering(ByVal sender As System.Object, ByVal e As Telerik.WinControls.UI.GridViewCustomFilteringEventArgs) Handles RadGridView1.CustomFiltering
            If Me.RadListControl1.SelectedItems.Count = 0 Then
                e.Visible = True
                Return
            End If
      
            e.Visible = False
            Dim found As Boolean
            For Each item As RadListDataItem In Me.RadListControl1.SelectedItems
                If String.Equals(item.Text, e.Row.Cells("Status").Value.ToString()) Then
                    found = True
                    Exit For
                End If
            Next
            e.Visible = found
        End Sub
      
      
    End Class
      
    Public Class MyStatus
      
        Public Sub New(ByVal name As String, ByVal status As String)
            Me.Name = name
            Me.Status = status
        End Sub
      
        Public Property Name As String
        Public Property Status As String
    End Class

    and here is a small video of it working
    Hope that helps
    Richard
  8. Dean Allan
    Dean Allan avatar
    12 posts
    Member since:
    Jan 2010

    Posted 15 Feb 2011 Link to this post

    Hey Richard,

    Thanks again for the assistance. The last example was great!

    I decided with a hybrid of your original offering.  I like the filter method for RadGrid I was using (mainly because I understood it), it was the functionality of standard listcontrol event handler that was holding me up.

    Your first example really solved the problem.  It provided me with an accurate representation of the events going on with the listcontrol. Taking that data, I created a second Sub that will handle popping the stack (an array) and then i'll build a new set of filters. It's a bit old school but should do the trick. It also let's me add other fields besides status to the filters.

    Something like this.

    Private Sub RadListControl_RadPropertyChanged(ByVal sender As Object, ByVal e As RadPropertyChangedEventArgs)
          If e.Property.Name = "Selected" Then
              Dim item As RadListDataItem = CType(sender, RadListDataItem)
              ModifyFilter(item.Text, item.Selected.ToString(),"status")
          End If
      End Sub
      Private Sub ModifyFilter(ByVal status As String, ByVal action As String, ByVal field as String)
          If action = "True" Then
              MsgBox("Add " & status) ' for debugging only
              'add to the stack
          Else
              MsgBox("Remove " & status) ' for debugging only
              'pop the stack
          End If
          'clear and rebuild the filters from the stack.
      End Sub


    Thanks again, 

    Dean.
  9. Dean Allan
    Dean Allan avatar
    12 posts
    Member since:
    Jan 2010

    Posted 15 Feb 2011 Link to this post

    Hey Richard,

    Here is my final code I came up with.  So far it seems to work. Thanks again, couldn't have gotten this far without your help!

    Private Sub RadListControl_RadPropertyChanged(ByVal sender As Object, ByVal e As RadPropertyChangedEventArgs)
          If e.Property.Name = "Selected" Then
              Dim item As RadListDataItem = CType(sender, RadListDataItem)
              ModifyFilter(item.Text, item.Selected.ToString())
          End If
      End Sub
      Private Sub ModifyFilter(ByVal newstatus As String, ByVal newaction As String)
          If newaction = "True" Then
              Me.RadGridView1.FilterDescriptors.LogicalOperator = FilterLogicalOperator.Or
              Me.RadGridView1.FilterDescriptors.Add("status", FilterExpression.BinaryOperation.[OR], newstatus)
          Else
              For Each FilterExpression In RadGridView1.FilterDescriptors
                  If FilterExpression.Value = newstatus Then
                      Me.RadGridView1.FilterDescriptors.Remove(FilterExpression)
                      Exit For
                  End If
              Next
              If RadGridView1.FilterDescriptors.Count = 0 Then ' check to see if all the filters are gone then clear if so.
                  RadGridView1.FilterDescriptors.Clear()
              End If
          End If
      End Sub
  10. Richard Slade
    Richard Slade avatar
    3000 posts
    Member since:
    May 2009

    Posted 16 Feb 2011 Link to this post

    Hi Dean,

    Glad that you have this all sorted now. I'm glad i could help. It's also good to get some feedback and see your final version. Nothing wrong with it, but do have a look at the demos on your PC too for the Custom Filtering. The custom filtering is quite simple but powerful and is really useful for these situations which you may find useful in the future. Anyway, glad you have it all working now.
    All the best
    Richard
Back to Top
UI for WinForms is Visual Studio 2017 Ready