Retrieving SfComboBox SelectedIndices From Inside SfPopup DataTemplate

I have a page in my application that utilizes the SfPopup to manage a set of filters. The filters are attached to several different Syncfusion Controls (SfSegmentedControl, SfComboBox, SfCheckBox, etc.)

I'm finding it difficult to authenticate the values selected by a ComboBox inside the SfPopup's DataTemplate. See Attached GIF for a visual of what I have and am trying to achieve.

This is what I have currently in my code:

XAML -- In my <ContentPage.Resources>
<DataTemplate x:Name="StatementFilterTemplate" x:Key="StatementFilterTemplate">
            <StackLayout>
                  <StackLayout
                        x:Name="warehouse_override_selection"
                        Orientation="Vertical">
                        <Label />
                        <combobox:SfComboBox
                            x:Name="warehouse_selection_drop"
                            Watermark="Select Warehouse"
                            DataSource="{Binding StatementWarehousesAvailable}"
                            DisplayMemberPath="WarehouseReference">
                            <combobox:SfComboBox.TokenSettings>
                                    <combobox:TokenSettings
                                        Style="{StaticResource StandardTokenStyle}"/>
                                    </combobox:SfComboBox.TokenSettings>
                            <combobox:SfComboBox.ItemTemplate>
                                    <DataTemplate>
                                        // Item Content
                                    </DataTemplate>
                            </combobox:SfComboBox.ItemTemplate>
                        </combobox:SfComboBox>
                </StackLayout>
        </StackLayout>
</DataTemplate>

XAML.CS -- In OnAppearing()
popupLayout.PopupView.AcceptCommand = new AcceptPopupCommand();

VIEWMODEL
public class AcceptPopupCommand : ICommand
    {
        private SfComboBox comboWarehouse;
        private SfComboBox comboChain;
        private SfComboBox comboLocation;

        private List<int> SelectedWarehouses = new List<int>();
        private List<int> SelectedChains = new List<int>();
        private List<int> SelectedLocations = new List<int>();

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            var stack = (parameter as SfPopupLayout).PopupView.ContentTemplate.CreateContent();
            var warehouseStack = (stack as StackLayout).FindByName<StackLayout>("warehouse_override_selection");
            comboWarehouse = (warehouseStack as StackLayout).FindByName<SfComboBox>("warehouse_selection_drop");
            Debug.WriteLine("Whs pop: " + comboWarehouse.SelectedIndices.ToJson());
            if(comboWarehouse.SelectedIndices != null)
            {
                foreach(var obj in ((List<int>)comboWarehouse.SelectedIndices))
                {
                    SelectedWarehouses.Add(obj);
                }
                MessagingCenter.Send<List<int>>(SelectedWarehouses, "WarehouseSelectedStatement");
            }
            comboChain = (warehouseStack as StackLayout).FindByName<SfComboBox>("chain_selection_drop");
            Debug.WriteLine("Chn pop: " + comboChain.SelectedIndices.ToJson());
            if (comboChain.SelectedIndices != null)
            {
                foreach (var obj in ((List<int>)comboChain.SelectedIndices))
                {
                    SelectedChains.Add(obj);
                }
                MessagingCenter.Send<List<int>>(SelectedChains, "ChainSelectedStatement");
            }
            comboLocation = (warehouseStack as StackLayout).FindByName<SfComboBox>("location_selection_drop");
            Debug.WriteLine("Loc pop: " + comboLocation.SelectedIndices.ToJson());
            if (comboLocation.SelectedIndices != null)
            {
                foreach (var obj in ((List<int>)comboLocation.SelectedIndices))
                {
                    SelectedLocations.Add(obj);
                }
                MessagingCenter.Send<List<int>>(SelectedLocations, "LocationSelectedStatement");
            }
        }
    }



It seems no matther what I try, I can't access the SfComboBox's SelectedIndices from this ICommand interface. What am I missing?

Attachment: Popup_Filters_3ed39e03.zip

7 Replies

KK Karthikraja Kalaimani Syncfusion Team February 14, 2020 02:03 PM UTC

Hi Matthew,

Thank you for contacting Syncfusion support.

Based on the provided information we have checked your query “SelectedIndices cannot access from ICommand” and we found that you have created a new ContentTemplate of PopupView on Execute method of Command class. So it tends to create a new ComboBox. So only we cannot access SelectedIndices in the ICommand class. To overcome this issue make a public ComboBox property in ICommand class and initialized that ComboBox on BindigContext changed the event of Warehouse_selection_drop. For more details please refer to the below attached sample and code snippet.


Code Example,


 
[.CS]
public partial class MainPage : ContentPage 
    { 
        public SfComboBox comboBox; 
 
        AcceptPopupCommand acceptCommand; 
 
        public MainPage() 
        { 
            InitializeComponent(); 
 
             
        } 
 
        private void Button_Clicked(object sender, EventArgs e) 
        { 
 
            popup.Show(); 
        } 
 
        protected override void OnAppearing() 
        { 
            base.OnAppearing(); 
            acceptCommand = new AcceptPopupCommand(); 
            popup.PopupView.AcceptCommand = acceptCommand; 
        } 
 
        private void Warehouse_selection_drop_BindingContextChanged(object sender, EventArgs e) 
        { 
            comboBox = (sender as SfComboBox); 
            acceptCommand.ComboBox = comboBox; 
        } 
    } 
 
 
public class AcceptPopupCommand : ICommand 
    { 
        public SfComboBox ComboBox { get; set; } 
 
        private List<int> SelectedWarehouses = new List<int>(); 
        private List<int> SelectedChains = new List<int>(); 
        private List<int> SelectedLocations = new List<int>(); 
 
        public event EventHandler CanExecuteChanged; 
 
        public AcceptPopupCommand() 
        { 
             
        } 
 
        public bool CanExecute(object parameter) 
        { 
            return true; 
        } 
 
        public void Execute(object parameter) 
        { 
            
            if (ComboBox.SelectedIndices != null) 
            { 
                foreach (var obj in ((List<int>)ComboBox.SelectedIndices)) 
                { 
                    SelectedWarehouses.Add(obj); 
                } 
                MessagingCenter.Send<List<int>>(SelectedWarehouses, "WarehouseSelectedStatement"); 
            } 
        } 
    } 
 
[XAML] 
<ContentPage.Resources> 
        <DataTemplate  x:Key="StatementFilterTemplate"> 
            <StackLayout> 
                <StackLayout 
                        x:Name="warehouse_override_selection" 
                        Orientation="Vertical"> 
                    <Label/> 
                    <combobox:SfComboBox 
                        BindingContextChanged="Warehouse_selection_drop_BindingContextChanged" 
                            x:Name="warehouse_selection_drop" 
                        MultiSelectMode="Token" 
                            Watermark="Select Warehouse" 
                            DataSource="{Binding MobileCollection}" 
                            DisplayMemberPath="Mobile"> 
                        <combobox:SfComboBox.ItemTemplate> 
                            <DataTemplate> 
                                <Label  Text="{Binding Mobile}"></Label> 
                            </DataTemplate> 
                        </combobox:SfComboBox.ItemTemplate> 
                    </combobox:SfComboBox> 
                </StackLayout> 
            </StackLayout> 
        </DataTemplate> 
    </ContentPage.Resources> 
 


Sample link : https://www.syncfusion.com/downloads/support/directtrac/general/ze/Popup_Demo_2-440618339.zip


We hope this helps, please let us know if need further assistance from us.

Regards,
Karthik Raja
 



MB Matthew Bailey February 21, 2020 02:10 PM UTC

That was exactly what I needed.

Now in reverse, since the Popup isn't 'Opened' via an ICommand, but rather handled via an EventHandler through popupLayout.Opening or popupLayout.Opened --- How do I attached the SelectedIndicies that I passed out through the AcceptCommand back into the SfComboBox when I reopen the popup?

Currently, after I initiate the AcceptCommand - the popup closes and my list of selected indexes are passed along to my MessagingCenter control. But when I open the SfPopup again, my SfComboBox is empty.

I need it to show the list of selected indexes that I previously selected. How do I achieve this?


SS Sivaraman Sivagurunathan Syncfusion Team February 24, 2020 02:01 PM UTC

Hi Matthew, 
 
Sorry for the inconvenience. 
 
Currently we are validating the reported issue, we will update the details on 26th  February 2020. 
 
Regards, 
Sivaraman 



KK Karthikraja Kalaimani Syncfusion Team February 26, 2020 01:11 PM UTC

Hi Matthew,

 
Thank you for your patience.

Your requirement can be achieved by storing the previously SelectedIndices of ComboBox in the closing event of SfPopupLayout and then assign that SelectedIndices to the ComboBox of MainPage class. For more details please refer to the below code snippet.


 
[XAML]
<ContentPage.Content> 
        <sfPopup:SfPopupLayout x:Name="popup" Closing="Popup_Closing"> 
            <sfPopup:SfPopupLayout.PopupView> 
                <sfPopup:PopupView ContentTemplate="{StaticResource StatementFilterTemplate}"> 
                sfPopup:PopupView> 
            sfPopup:SfPopupLayout.PopupView> 
            <sfPopup:SfPopupLayout.Content> 
                <Button Text="clickTo Show popup" Clicked="Button_Clicked">Button> 
            sfPopup:SfPopupLayout.Content> 
        sfPopup:SfPopupLayout> 
    ContentPage.Content>

[.CS]
public
partial class MainPage : ContentPage 
    { 
        public SfComboBox comboBox; 
        List<int> selectedIndices = new List<int>();
….
 
private void Warehouse_selection_drop_BindingContextChanged(object sender, EventArgs e) 
        { 
            comboBox = (sender as SfComboBox); 
            if (selectedIndices != null) 
            comboBox.SelectedIndices = selectedIndices; 
            acceptCommand.ComboBox = comboBox; 
            
        }
…..

private
void Popup_Closing(object sender, Syncfusion.XForms.Core.CancelEventArgs e) 
        {
            selectedIndices.Clear();
 
            foreach (var obj in ((List<int>)acceptCommand.ComboBox.SelectedIndices)) 
            { 
                selectedIndices.Add(obj); 
            }   
        }
   }
 
} 


About Closing Event in SfPopupLayout :
https://help.syncfusion.com/xamarin/popup/popup-events#closing-event

Regards,
Karthik Raja 



MB Matthew Bailey April 27, 2020 01:34 PM UTC

Okay - so this method of using BindingContextChanged has been exactly what I was looking for but I have a follow up question.

1. I'm using a ViewModel for all my data binding, and it seems that I need to attach the bound data within the EventHandler otherwise the control doesn't display the current bound values - in my current application my codebehind doesn't handle the BindingContext = new ViewModel() assignment, so I don't have direct access to the VM in the code behind. So is there a way to build this in a ViewModel:
private void Warehouse_selection_drop_BindingContextChanged(object sender, EventArgs e) 
        { 
            comboBox = (sender as SfComboBox); 
            acceptCommand.ComboBox = comboBox; 
        } 




KK Karthikraja Kalaimani Syncfusion Team April 28, 2020 01:39 PM UTC

Hi Matthew,

Thanks for the update. 

Currently, we are validating your requirement. So, we will validate and update you further details on or before 30th April 2020. We appreciate your patience until then.

Regards,
Karthik Raja




KK Karthikraja Kalaimani Syncfusion Team April 30, 2020 10:38 AM UTC

Hi Matthew,

We have checked your requirement and it not possible to move that process for getting the selectedIndices of ComboBox from BindingContextChanged event to ViewModel. Because ComboBox loaded as DataTemplate and the only way to get the selected Indices of ComboBox from DataTemplate via BindingContextChanged event. We have linked the below stack overflow discussions about getting a view from DataTemplate.

StackOverFlow link :
https://stackoverflow.com/questions/49373982/access-views-inside-a-datatemplate-at-runtime-in-xamarin-forms

Regards,
Karthik Raja 


Loader.
Up arrow icon