This is a migrated thread and some comments may be shown as answers.

How To Bind To AutoCompleteView SelectedItems

6 Answers 199 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Bruce
Top achievements
Rank 2
Bruce asked on 07 Jan 2020, 03:32 PM

[Our RadAutoCompleteView resides within a RadTreeView]

I'm trying to utilize the Tokens feature of the RadAutoCompleteView control for our POC and I'm unable to get a hold of the selected Tokens. At first, I tried data binding to the Tokens property (Mode=TwoWay) and my view model property was never being set after selecting any number of tokens. So, this might be another bug.

I gave up on trying to bind to Tokens (for now) and tried to utilize the code-behind to directly see which Tokens have been selected. Unfortunately, my named components are not visible to the code behind if they're under a DataTemplate inside a RadTreeView.

In the following code example, "TopicsTreeViewDescriptor" IS visible to the code-behind, but "TopicsExpandCollapseIndicator" (used simply for this test) and "TopicsAutoCompleteView" are NOT visible to the code-behind making it impossible for me to determine which Tokens have been selected.

 

<telerikDataControls:RadTreeView x:Name="TopicsTreeView" Grid.Row="2" ItemsSource="{Binding Topics}" CheckBoxMode="Propagate" WidthRequest="300">
    <telerikDataControls:TreeViewDescriptor x:Name="TopicsTreeViewDescriptor" ItemsSourcePath="Items" DisplayMemberPath="DisplayName" TargetType="{x:Type v1:Topic}">
        <telerikDataControls:TreeViewDescriptor.ItemTemplate>
            <DataTemplate x:Name="TopicsDataTemplate">
                <Grid>
                    <!--<Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>-->
                    <Grid Margin="{Binding Path=Level, Converter={StaticResource LevelToMarginConverter}}"
                          HeightRequest="40"
                          IsVisible="{Binding Item.ShowAutoComplete, Converter={StaticResource InverseBooleanConverter}}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition>
                                <ColumnDefinition.Width>
                                    <OnPlatform x:TypeArguments="GridLength" Default="Auto">
                                        <On Platform="UWP">45</On>
                                    </OnPlatform>
                                </ColumnDefinition.Width>
                            </ColumnDefinition>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <treeView:ExpandCollapseIndicator x:Name="TopicsExpandCollapseIndicator"
                                                          Grid.Column="0"
                                                          FontSize="Medium"
                                                          WidthRequest="10"
                                                          Margin="15,0"
                                                          VerticalTextAlignment="Center"
                                                          IsLoading="{Binding Path=IsLoading}"
                                                          IsLoadOnDemandEnabled="{Binding Path=IsLoadOnDemandEnabled}"
                                                          IsExpanded="{Binding Path=Item.Expanded, Mode=TwoWay}"
                                                          IsLeaf="{Binding Path=IsLeaf}"/>
                        <Image Grid.Column="1"
                               VerticalOptions="Center"
                               Source="{Binding Item.IconName, Converter={StaticResource ImageSourceConverter}}"
                               IsVisible="{Binding Item.ShowAutoComplete, Converter={StaticResource InverseBooleanConverter}}"/>
                        <primitives:RadCheckBox Grid.Column="1"
                                                IsChecked="{Binding Path=Item.Checked, Mode=TwoWay}"
                                                IsVisible="{Binding Path=Item.IsCheckBoxVisible}"
                                                VerticalOptions="Center" />
                        <treeView:ItemText Grid.Column="2"
                                           Margin="8,0,0,0"
                                           VerticalOptions="Center"
                                           Text="{Binding Item.DisplayName}" />
                    </Grid>
                    <Grid x:Name="AutoCompleteGrid" Margin="{Binding Path=Level, Converter={StaticResource LevelToMarginConverter}}"
                          IsVisible="{Binding Item.ShowAutoComplete}">
                        <input:RadAutoCompleteView x:Name="TopicsAutoCompleteView"
                                                   Text="{Binding Item.SearchText, Mode=TwoWay}"
                                                   ItemsSource="{Binding Item.Items}"
                                                   Watermark="Search here..."
                                                   DisplayMode="Tokens"
                                                   IsClearButtonVisible="True"
                                                   CompletionMode="StartsWith"
                                                   Tokens="{Binding Item.SelectedItems, Mode=TwoWay}"
                                                   SuggestionItemSelected="RadAutoCompleteView_OnSuggestionItemSelected"
                                                   TextSearchPath="PortfolioTransactionCustomValue"
                                                   SearchThreshold="1"/>
                    </Grid>
                </Grid>
            </DataTemplate>
        </telerikDataControls:TreeViewDescriptor.ItemTemplate>
    </telerikDataControls:TreeViewDescriptor>
</telerikDataControls:RadTreeView>

6 Answers, 1 is accepted

Sort by
0
Bruce
Top achievements
Rank 2
answered on 07 Jan 2020, 07:15 PM
A fellow developer pointed out that I'm apparently guilty of a neophyte XAML assumption for one major part of my above issue. Since the RadAutoCompleteView is part of a DataTemplate it's dynamically created and not visible to the code-behind (DOH!). Since that's my likely issue with trying to get a hold of the control in the code-behind, then I'm still stuck trying to get access to the Tokens. Hence, maybe the issue/bug that needs to be addressed is the RadAutoCompleteView and why I can't have the Tokens write back to the viewmodel and/or have another way to gain access to that listed of selected tokens.
0
Yana
Telerik team
answered on 08 Jan 2020, 02:43 PM

Hi Bruce,

Thank you for sending the snippet. 

Indeed, you will not be able to access the AutoCompleteView (or any other control) by id when it is placed inside a template -  not only that it is dynamically created but there are different RadAutoCompleteView instances for each item using the template.

As to the issue at hand - Tokens collection is read-only and you can only add items to it.  When using two-way binding the framework tries to entirely set the respective property instead of adding or removing specific items.

So, in this case, you can use OneWay binding  - bind Tokens to a collection of type ObservableCollection<object> in the business object and use its CollectionChanged event - it is fired every time an item is added or removed from the collection.  I have attached a sample example based on the provided XAML to show you exactly how this would work.

Please download the attachment and give it a try.  I hope that would be helpful.

Regards,
Yana
Progress Telerik

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Bruce
Top achievements
Rank 2
answered on 08 Jan 2020, 03:43 PM

I implemented basically exactly what your given solution changed and it still doesn't work. In fact, the Set of SelectedItems is never hit when the code is run and suggested items are selected. The main changes I noted and performed were removing TwoWay binding (so the OneWay default is used) and adding code to the Set so that the CollectionChanged event could be utilized (which is never hit during testing). Is there something else I'm missing?

Below is our Topic class so that you can see how we've set up the tree hierarchy more explicitly (btw...I tried attaching the file but I was getting an error when trying to do that).

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Prism.Mvvm;
 
namespace JHI.Data.Models.ResearchHub.v1
{
    public class Topic: BindableBase
    {
 
        #region Constructor
 
        public Topic()
        {
        }
 
        #endregion
 
        #region Properties
 
        private Guid _id;
        public Guid Id
        {
            get { return _id; }
            set
            {
                _id = value;
            }
        }
 
        private bool _expanded = false;
        public bool Expanded
        {
            get { return _expanded; }
            set { SetProperty(ref _expanded, value); }
        }
 
        private bool? _checked = false;
        public bool? Checked
        {
            get { return _checked;}
            set { SetProperty(ref _checked, value); }
        }
 
        //private bool _showNode;
        public bool ShowNode
        {
            get { return !IsTextSearch.GetValueOrDefault(); }
            //get { return (Name == "Account" || Name == "SymbolId"); }
            //set { SetProperty(ref _showAutoComplete, value); }
        }
 
        //private bool _showAutoComplete;
        public bool ShowAutoComplete
        {
            get { return ((IsTextSearch == false) && (Name != "Keyword")); }
            //get { return (Name == "Account" || Name == "SymbolId"); }
            //set { SetProperty(ref _showAutoComplete, value); }
        }
 
        //private bool _isCheckBoxVisible;
        public bool IsCheckBoxVisible
        {
            get { return ((IsTextSearch == null) && !((Name == "Keyword") || (DisplayName == "Company Tickers") || (DisplayName == "Accounts"))); }
            //get { return (Name != "Account" && Name != "SymbolId"); }
            //set { SetProperty(ref _isCheckBoxVisible, value); }
        }
 
        public bool Selected { get; set; } = false;
 
        // ParentId cannot be included on the model -- Telerik TreeView control can't handle it exising if it's null
        //private Guid? _parentId;
        //public Guid? ParentId
        //{
        //    get { return _parentId; }
        //    set
        //    {
        //        _parentId = value;
        //    }
        //}
 
        private Guid? _hashId;
        public Guid? HashId
        {
            get { return _hashId; }
            set
            {
                _hashId = value;
            }
        }
 
        private Guid? _preHashId;
        public Guid? PreHashId
        {
            get { return _preHashId; }
            set
            {
                _preHashId = value;
            }
        }
 
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }
 
        private string _portfolioTransactionCustomValue;
        public string PortfolioTransactionCustomValue
        {
            get { return _portfolioTransactionCustomValue; }
            set
            {
                _portfolioTransactionCustomValue = value;
            }
        }
 
        private string _displayName;
        public string DisplayName
        {
            get { return _displayName; }
            set
            {
                _displayName = value;
            }
        }
 
        private string _iconName;
        public string IconName
        {
            get { return _iconName; }
            set
            {
                _iconName = value;
            }
        }
 
        private bool? _isCategory;
        public bool? IsCategory
        {
            get { return _isCategory; }
            set
            {
                _isCategory = value;
            }
        }
 
        private bool? _isTextSearch;
        public bool? IsTextSearch
        {
            get { return _isTextSearch; }
            set
            {
                _isTextSearch = value;
            }
        }
 
        private string _script;
        public string Script
        {
            get { return _script; }
            set
            {
                _script = value;
            }
        }
 
        private int _sortIndex;
        public int SortIndex
        {
            get { return _sortIndex; }
            set
            {
                _sortIndex = value;
            }
        }
 
        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
            }
        }
 
        private DateTime _created;
        public DateTime Created
        {
            get { return _created; }
            set
            {
                _created = value;
            }
        }
 
        private DateTime _modified;
        public DateTime Modified
        {
            get { return _modified; }
            set
            {
                _modified = value;
            }
        }
 
 
        private List<Topic> _items;
        public List<Topic> Items
        {
            get { return _items; }
            set
            {
                _items = value;
            }
        }
        /*
        private ObservableCollection<string> _filteredItems;
        public ObservableCollection<string> FilteredItems
        {
            get { return _filteredItems; }
            set { SetProperty(ref _filteredItems, value); }
        }
        */
        private ObservableCollection<Topic> _selectedItems;
        public ObservableCollection<Topic> SelectedItems
        {
            get { return _selectedItems; }
            set
            {
                if (_selectedItems != value)
                {
                    if (_selectedItems != null)
                    {
                        _selectedItems.CollectionChanged -= SelectedSource_CollectionChanged;
                    }
 
                    SetProperty(ref _selectedItems, value);
 
                    if (_selectedItems != null)
                    {
                        _selectedItems.CollectionChanged += SelectedSource_CollectionChanged;
                    }
                }
            }
        }
 
        private void SelectedSource_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
        }
 
        private string _searchText;
        public string SearchText
        {
            get { return _searchText; }
            set
            {
                if (SetProperty(ref _searchText, value))
                {
                    //RaisePropertyChanged(nameof(FilteredItems));
                }
            }
        }
 
        private Topic _parentTopic;
        public Topic ParentTopic
        {
            get { return _parentTopic; }
            set
            {
                _parentTopic = value;
            }
        }
 
        private string _targetConsumer;
        public string TargetConsumer
        {
            get { return _targetConsumer; }
            set
            {
                _targetConsumer = value;
            }
        }
 
        private bool? _isNew;
        public bool? IsNew
        {
            get { return _isNew; }
            set
            {
                _isNew = value;
            }
        }
 
        private bool? _isActive;
        public bool? IsActive
        {
            get { return _isActive; }
            set
            {
                _isActive = value;
            }
        }
 
        #endregion
 
    }
}

 

0
Accepted
Yana
Telerik team
answered on 08 Jan 2020, 04:10 PM

Hi Bruce,

Looking at the code I noticed that the SelectedItems is of type ObservableCollection<Topic> and it should be ObservableCollection<object> as that's the type of the Tokens property.  In the collection changed event handler you can cast it to the needed type.

Please modify it and let me know how it goes.

Regards,
Yana
Progress Telerik

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Bruce
Top achievements
Rank 2
answered on 08 Jan 2020, 04:40 PM

That was my issue...I didn't match the signature for the SelectedItems (Topics) to work properly.

Since this was not a bug and it should be associated with the AutoCompleteView control, please feel free to move and rename this thread.

Thank you!

0
Lance | Manager Technical Support
Telerik team
answered on 08 Jan 2020, 05:32 PM

Hello Bruce,

I'm happy to see this is resolved.

I've re-titled this public thread, and moved it into AutocompleteView forums, so that it would be more easily discovered for anyone else having a similar issue. Thank you.

Regards,
Lance | Team Lead - US DevTools Support
Progress Telerik

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
TreeView
Asked by
Bruce
Top achievements
Rank 2
Answers by
Bruce
Top achievements
Rank 2
Yana
Telerik team
Lance | Manager Technical Support
Telerik team
Share this question
or