Can I programmatically search an tem in RadTreeListView in pure MVVM WPF application?

8 posts, 1 answers
  1. Eugene
    Eugene avatar
    83 posts
    Member since:
    Jan 2016

    Posted 28 Jun Link to this post

    I have an instance of RadTreeListView in my WPF MVVM Prism 6 application (my application is pure MVVM without code behind). I'm interested in searching of specified item in RadTreeListView in a programmatical way. The instance of RadTreeView in my application is bound to an instance of ObservableCollection comprising hierarchical data.

    private ObservableCollection<ProfileElementType> _myCollection = new ObservableCollection<ProfileElementType>();
     
    // This property is the data source for RadTreeListView.
    public ObservableCollection<ProfileElementType> MyCollection
    {
        get{return this _myCollection;}
        set{this.SetProperty(ref this._myCollection, value);}
    }

    ProfileElementType class is the base class for two classes that are derived from him. These derived classes are: Group and Register. The definition of ProfileElementType class, Group class and Register class you can see in my post in Stackoverflow at:  http://stackoverflow.com/questions/37058259/why-is-invalideoperationexception-thrown-when-i-try-to-serialize-to-xml-an-obser .  In "Hierarhy.PNG" attached file you can see how hierarchy is displayed in RadTreeView on the screen. In pure MVVM I can use only properties and mapped to commands events. But I can't use control's methods there. Is it possible to realize search in such RadTreeView in pure MVVM application?

    P.S. If you need any additional Information please tell about it.

  2. Eugene
    Eugene avatar
    83 posts
    Member since:
    Jan 2016

    Posted 29 Jun in reply to Eugene Link to this post

    Gentlemen, if you give me an example of C# WPF MVVM application where searching of specified item in RadTreeListView is realized, it'll be perfectly well. I will be very grateful to you for that. I again draw your attention that my application is pure MVVM one (without any code-behind) so that I can use there only the bound properties of RadTreeListView and mapped-on-commands events of RadTreeListView. I can't use methods of RadTreeListView in pure MVVM application because the instance of RadTreeListView is in the View and according to MVVM principles "ViewModel doesn't know about View". I am hope for your help.
  3. UI for WPF is Visual Studio 2017 Ready
  4. Stefan X1
    Admin
    Stefan X1 avatar
    514 posts

    Posted 01 Jul Link to this post

    Hello Eugene,

    In case I am not missing something, you should be able to search for a given item directly in the source collection in the view model. In order to ensure that we are on the same page, can you please share more details on the exact requirement, so I can further assist you?

    Best Regards,
    Stefan X1
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  5. Eugene
    Eugene avatar
    83 posts
    Member since:
    Jan 2016

    Posted 04 Jul in reply to Stefan X1 Link to this post

    OK, Stefan. First thank you very much for your support and help.You've written: "...can you please share more details on the exact requirement, so I can further assist you?". OK. I need in the function for searching of specified item (representing a device register) in RadTreeListView. This function should execute in the ViewModel and searches for a specified item (device register) directly in the source ObservableCollection to which RadTreeListView is bound in the View. However, if the search is successful, the found item (device register) must be selected in the RadTreeListView as current selected item.  Below I present you some information about how to define data that is displayed in the RadTreeListView. Please see that RadTreeListView is bound to ObservableCollection as following:

    <telerik:RadTreeListView x:Name="Hierarchical" Grid.Row="2" Grid.Column="0" AutoGenerateColumns="False" AutoExpandItems="True" IsSynchronizedWithCurrentItem="True"
                                         ItemsSource="{Binding ProfileTreeRoot.ChildProfileElenents}" Visibility="{Binding AreRegistersInHierarchyVisible}">
       <telerik:RadTreeListView.ChildTableDefinitions>
          <telerik:TreeListViewTableDefinition ItemsSource="{Binding ChildProfileElenents}"/>
       </telerik:RadTreeListView.ChildTableDefinitions>
       <telerik:RadTreeListView.Columns>
          <telerik:GridViewDataColumn IsReadOnly="True" DataMemberBinding="{Binding Name}" Header="Наименование">
          <telerik:GridViewDataColumn.CellStyle>
              <Style TargetType="{x:Type telerik:GridViewCell}">
                  <Setter Property="FontWeight" Value="SemiBold"/>
              </Style>
          </telerik:GridViewDataColumn.CellStyle>
          </telerik:GridViewDataColumn>
              <telerik:GridViewDataColumn DataMemberBinding="{Binding CurrentValue}" Header="Текущее значение"/>
       </telerik:RadTreeListView.Columns>
       <telerik:EventToCommandBehavior.EventBindings>
          <telerik:EventBinding
              Command="{Binding HandleProfileElementSelectionChangedCommand}"
              EventName="SelectionChanged"
              PassEventArgsToCommand="True"/>
          <telerik:EventBinding
              Command="{Binding HandleRowLoadedCommand}"
              EventName="RowLoaded"
              PassEventArgsToCommand="True"/>
       </telerik:EventToCommandBehavior.EventBindings>
    </telerik:RadTreeListView>

    As you can see from XAML above, binding of RadTreeListView to datasource is:

    ItemsSource="{Binding ProfileTreeRoot.ChildProfileElenents}"

    Where 'ProfileTreeRoot.ChildProfileElenents' is an ObservableCollection of hierarchical elements:

    private ObservableCollection<ProfileElementType> _childProfileElenents;
    public ObservableCollection<ProfileElementType> ChildProfileElenents
    {
       get { return this._childProfileElenents; }
       set { this._childProfileElenents = value; }
    }

    This collection comprises instances of 'ProfileElementType' class. Please see its definition below:

    public class ProfileElementType : BindableBase, IProfileElementType
    {
        #region Fields
     
        // Type name for the object's class that is derived from this class.
        // It can be one of the folowing: "Group" or "Register" or "Device".
        private string _elementTypeName;
     
        #endregion
     
        #region Properties
     
        // Gets or sets type name for the object's class that is derived from this class.
        public string ElementTypeName
        {
           get { return this._elementTypeName; }
           set { this._elementTypeName = value; }
        }
        #endregion
     
        #region IProfileElementType Implementation
     
        // Type of the object's class that is derived from this class.
        // It can be one of the folowing: Group or Register or Device.
        private Type _elementType;
     
        // Gets or sets type of the object's class that is derived from this class.
        public Type ElementType
        {
           get { return this._elementType; }
           set { this._elementType = value; }
        }
     
        #endregion
    }

    If you look at the picture in Hierarchical_2.PNG attached file you'll see two columns there: "Наименование" ("Name" in English) and "Текущее значение" ("Current Value" in English). Next, I will refer to these columns name in English (I bag your pardon for Russian headers). As you can see data in "Name" column has two levels of hierarchy. The first level is group names and the second level is register names. Each group can comprise some registers and some other groups. Each group of those that are shown in the picture is represented by Group class. Each register - by Register class. Below are definitions of these two clases. To very begin is definition of Group class:

    public class Group : ProfileElementType
    {
        #region Fields
     
        // The name of group
        private string name;
        // Brief description of group.
        private string description;
        // The collection of elements which are the children elements of this group.
        // These elements can be of Group class instances or Register class instances.
        private ObservableCollection<ProfileElementType> _childProfileElenents;
        // Parent group whose ChildProfileElenents collection comprises this Group instance.
        private Group parent;
     
        #endregion
     
        #region Constructors
        public Group()
        {
           this.ElementType = this.GetType();
           this.ElementTypeName = this.ElementType.Name;
           this.Name = "Group 1";
           this.ChildProfileElenents = new ObservableCollection<ProfileElementType>();
        }
        #endregion
     
        #region Properties
     
        /// <summary>
        /// Gets or sets the name of the group.
        /// </summary>
        public string Name
        {
            get { return this.name; }
            set { this.SetProperty(ref this.name, value); }
        }
        /// <summary>
        /// Gets or sets the brief description of the group.
        /// </summary>
        public string Description
        {
            get { return this.description; }
            set { this.SetProperty(ref this.description, value); }
        }
        /// <summary>
        /// Gets or sets the collection of elements which are the children elements of this group.
        /// These elements can be of Group class instances or Register class instances
        /// </summary>
        public ObservableCollection<ProfileElementType> ChildProfileElenents
        {
            get { return this._childProfileElenents; }
            set { this.childProfileElenents = value; }
        }
        /// <summary>
        /// Gets or sets the parent group whose ChildProfileElenents collection comprises this Group instance.
        /// </summary>
        public Group Parent
        {
            get { return this.parent; }
            set { this.parent = value; }
        }
        #endregion
    }

    And here is the definition of Register class:

    public class Register : ProfileElementType
    {
       #region Fields
        
       private int number;
       private string name;
       private string description;
       private string currentValue;
       private string defaultValue;
       private string minimalValue;
       private string maximalValue;
       private string dataTypeName;
       private RegisterDataAccess accessToData;
       private Group parent;
        
       #endregion
     
       #region Constructors
       public Register()
       {
           this.ElementType = this.GetType();
           this.ElementTypeName = this.ElementType.Name;
           this.Name = "REgister 1";
           this.AccessToData = RegisterDataAccess.Read_Write;
       }
       #endregion
     
       #region Properties
     
       // Register's address in device.
       public int Number
       {
           get { return this.number; }
           set { this.SetProperty(ref this.number, value); }
       }
       // The name of the register.
       public string Name
       {
          get { return this.name; }
          set { this.SetProperty(ref this.name, value); }
       }
       // The breif description of the register.
       public string Description
       {
          get { return this.description; }
          set { this.SetProperty(ref this.description, value); }
       }
       // The register current value.
       public string CurrentValue
       {
          get { return this.currentValue; }
          set { this.SetProperty(ref this.currentValue, value); }
       }
       // The register default value.
       public string DefaultValue
       {
          get { return this.defaultValue; }
          set { this.SetProperty(ref this.defaultValue, value); }
       }
       // The register Minimal Value.
       public string MinimalValue
       {
          get { return this.minimalValue; }
          set { this.SetProperty(ref this.minimalValue, value); }
       }
       // The register Maximal Value.
       public string MaximalValue
       {
          get { return this.maximalValue; }
          set { this.SetProperty(ref this.maximalValue, value); }
       }
       // The register's value data type.
       public string DataTypeName
       {
          get { return this.dataTypeName; }
          set { this.SetProperty(ref this.dataTypeName, value); }
       }
       // The user access to register's data from application.
       public RegisterDataAccess AccessToData
       {
          get { return this.accessToData; }
          set { this.SetProperty(ref this.accessToData, value); }
       }
       // Parent group whose ChildProfileElenents collection comprises this Register instance.
       public Group Parent
       {
          get { return this.parent; }
          set { this.parent = value; }
       }
        
       #endregion
    }

    That is, under the guise of instances ProfileElementTipe the collection includes both Group class instances and Register class instances for displaying their information on the screen. So above I presented information to you which must  give you understanding how to help me. I hope for your help very much.

    Eugene.

  6. Stefan X1
    Admin
    Stefan X1 avatar
    514 posts

    Posted 05 Jul Link to this post

    Hello Eugene,

    Thanks for the update.

    For this scenario, you can benefit from the SelectedItem property of RadTreeListView. You can define, for example, a SelectedRegister property in the view model and bind the aforementioned one of the control to it. When the search is performed, you can set the SelectedRegister property to be the found item.

    You may also find the Stop Showing the Unfocused State help topic. It is for RadGridView, but the same approach applies to RadTreeListView as well.

    Hope this helps.

    Best Regards,
    Stefan X1
    Telerik by Progress
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  7. Eugene
    Eugene avatar
    83 posts
    Member since:
    Jan 2016

    Posted 06 Jul in reply to Stefan X1 Link to this post

    Thank you very much, Stefan. I'll try binding 'View.RadTreeListView.SelectedItem --> ViewModel.SelectedRegister as you've adviced. I'll begin try it tomorrow (because just now I'm busy in another task). I will close the topic when I complete with the register search in RadTreeListView. OK.
  8. Eugene
    Eugene avatar
    83 posts
    Member since:
    Jan 2016

    Posted 08 Jul in reply to Eugene Link to this post

    Hi, Stefan. I've done register's search. It works. But I have a little problem hm... Is is the following. The flowmeter has about 1000 registers. On the screen (at the same time) a user can see in RadTreeListView about 25 registers. So, if the first register in the top of the RadTreeListView is selected, and a user asked a search of the last register in the end of the list then the search function finds the register perfectly, but there is no auto-scroll. So user must scroll to the found register (to see this register) manually with the mouse. How to automatically scroll the contents of the RadTreeListView to watch the register that was found? In MVVM application I can't use ScrollIntoView and ScrollIndexIntoView methods. Is there a way to auto scrolling to register found to watch it in MVVM? Thank you very much in advance.
  9. Answer
    Stefan X1
    Admin
    Stefan X1 avatar
    514 posts

    Posted 08 Jul Link to this post

    Hello Eugene,

    The built-in mechanism for such requirement is demonstrated in the Scrolling help topic. Can you please check it out?

    Regards,
    Stefan X1
    Telerik by Progress
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Back to Top
UI for WPF is Visual Studio 2017 Ready