How can I display SfComboBox when a button is clicked, using a GridTemplateColumn? ~ Split from 197125

Hi thanks for the reply I played around with the code you supplied but having looked at it, I think having the DetailsView/Grid is unneeded.

I would like to do the following instead:
- Keep everything on the same grid without a details grid.

- There would be a template column that in the cell view shows a button that shows the amount of Clients associated with the staff member.

- When the user clicks the button, it then displays a combobox that supports multiple selection in the edit view.


These images represent what I am trying to achieve: 


Image 1 - Before going into edit mode


before_menu.png


Image 2 - After click on the button


menu_open_b.png


7 Replies 1 reply marked as answer

SB Sweatha Bharathi Syncfusion Team July 18, 2025 02:32 PM UTC

Hi Alfred Smith,

We have reviewed your query. To proceed further, we requested the following details:

  1. When the button is clicked, the ComboBox is displayed. After selection, do you want the button to reappear in the UI instead of the ComboBox? If yes, please share the following details:
       
  1.           a. In the image you provided, on button click, "View 2" is shown and the ComboBox appears. Could you please confirm whether you expect: The selected items from the ComboBox to be displayed on the button, or the count of selected items to be shown on the button?
        
              b. And kindly confirm when you want the button to be shown again after the ComboBox has been opened.

              c. Can you confirm whether you are using the EditTemplate to place the SfComboBox, or are you only using the CellTemplate where the button is placed? Also, on button click, do you intend to display the SfComboBox?

  1. This information will help us proceed further and provide an accurate solution.

Regards,
Sweatha B


AS Alfred Smith replied to Sweatha Bharathi July 18, 2025 06:07 PM UTC

  1. Yes after selection and the combox is closed the button should reappear 
  2. I only expect the total amount of selected items to be shown on the button, as showing the client's names for instance would get messy if many are chosen.
  3. The button should only be shown after the selection has been made and the Combobox is closed
  4. I have the button placed in the Cell Template and the ComboBox in the EditTemplate
  5. When the user clicks the button the ComboBox should appear. Alternatively instead of a button the cell could just display the number of clients selected ie it might just show "2" and then when it is double clicked it shows the combo box in the same manner how one normally edits a field in the datagrid.


SB Sweatha Bharathi Syncfusion Team July 21, 2025 02:28 PM UTC

Alfred Smith,


We have reviewed your query. To display a SfComboBox in a GridTemplateColumn while performing editing, and to show the selected items count of the ComboBox in the control placed within the CellTemplate , it can be achieved in two ways:


Solution 1:
When using a TextBlock as CellTemplate


You can place a TextBlock as the CellTemplate in the GridTemplateColumn, and use an SfComboBox as the EditTemplate. For the TextBlock, use a value converter to display the count of selected items.

In the converter, you can split the ClientName property using a separator (such as hypen) to determine the number of selected items, and then return that count to be displayed in the TextBlock Text property.

Code snippet to display the SfComboBox when Doubleclicking on TextBlock:

<dataGrid:GridTemplateColumn MappingName="ClientName"

                              HeaderText="ClientDetails">

     <dataGrid:GridTemplateColumn.CellTemplate>

         <DataTemplate>

             <TextBlock Text="{Binding ClientName, Converter={StaticResource ClientNameConverter}}"

                                 HorizontalAlignment="Center"

                                VerticalAlignment="Center"/>

         </DataTemplate>

     </dataGrid:GridTemplateColumn.CellTemplate>

     <dataGrid:GridTemplateColumn.EditTemplate>

         <DataTemplate>

             <editors:SfComboBox x:Name="sfComboBox"

                                                    DisplayMemberPath="FullName"

                                                    DataContext="{Binding AllClients,Source={StaticResource ViewModel}}" 

                                                    Loaded="OnLoaded"

                                                    SelectionMode="Multiple"

                                                    Width="300"

                                                    SelectionChanged="OnSelectionChanged" />

         </DataTemplate>

     </dataGrid:GridTemplateColumn.EditTemplate>

 </dataGrid:GridTemplateColumn>


Code snippet for show the selected items count in TextBlock:

public class ClientNameConverter : IValueConverter

 {

     public object Convert(object value, Type targetType, object parameter, string language)

     {

         if (value is string clientName)

         {

             // Assuming `-` is the delimiter

             var parts = clientName.Split('-');

             int count = parts.Length;

             return $" View {count}";

         }

 

         return value;

     }

 

     public object ConvertBack(object value, Type targetType, object parameter, string language)

     {

         throw new NotImplementedException();

     }

 }



Solution 2: When using a Button as CellTemplate

                  You can place a Button as the CellTemplate in the GridTemplateColumn, and use an SfComboBox as the EditTemplate. To display the count of selected items, use a value converter bound to the Button Content property.

In the converter, you can split the ClientName property using a separator (such as a hyphen) to calculate the number of selected items, and return that count as a string to be displayed on the button

Code snippet to placed Button as CellTemplate:

<dataGrid:GridTemplateColumn MappingName="ClientName"

                                                          HeaderText="ClientDetails">

     <dataGrid:GridTemplateColumn.CellTemplate>

         <DataTemplate>

             <StackPanel>

                 <Button Content="{Binding ClientName, Converter={StaticResource ClientNameConverter}}"

                                HorizontalAlignment="Center"

                               VerticalAlignment="Center"

                               Click="OnClick"/>

             </StackPanel>

         </DataTemplate>

     </dataGrid:GridTemplateColumn.CellTemplate>

     <dataGrid:GridTemplateColumn.EditTemplate>

         <DataTemplate>

             <editors:SfComboBox x:Name="sfComboBox"

                                                    DisplayMemberPath="FullName"

                                                    DataContext="{Binding AllClients,Source={StaticResource ViewModel}}" 

                                                    Loaded="OnLoaded"

                                                    SelectionMode="Multiple"

                                                    Width="150"

                                                    SelectionChanged="OnSelectionChanged" />

         </DataTemplate>

     </dataGrid:GridTemplateColumn.EditTemplate>

 </dataGrid:GridTemplateColumn>


When the button is clicked, you can programmatically display the SfComboBox by handling the button click event. In the click event handler, use the PointToCellRowColumnIndex method of the SfDataGrid to get the current row and column index. This can be done by capturing the position from the PointerMoved event.

Once you retrieve the row and column index, set the CurrentCell to that index and call the BeginEdit method to activate the edit mode, which will display the SfComboBox.

Code snippet to display the SfComboBox when clicking on Button:

private void OnClick(object sender, RoutedEventArgs e)

 {

     var visualContainer = sfDataGrid.GetVisualContainer();

     if(visualContainer != null && sfDataGrid.SelectionController != null && sfDataGrid.SelectionController.CurrentCellManager != null)

     {

         var rowColumnIndex = visualContainer.PointToCellRowColumnIndex(lastMousePosition);

         if (rowColumnIndex != null)

             sfDataGrid.MoveCurrentCell(rowColumnIndex);

         sfDataGrid.SelectionController.CurrentCellManager.BeginEdit();

     }

 }

private void OnPointerMoved(object sender, PointerRoutedEventArgs e)

{

    lastMousePosition = e.GetCurrentPoint(sfDataGrid).Position;

}


Additionally, to achieve different ItemsSource values for combobox based on the parent row, you can handle the Loaded event of the SfComboBox. In this event, you can retrieve the current data row using the FindParent method. Based on the row's ID, you can then retrieve the matching values from the ComboBox DataContext. Using these values, you can bind the appropriate ItemsSource to the SfComboBox.

private void OnLoaded(object sender, RoutedEventArgs e)

{

    var comboBox = sender as SfComboBox;

    if (comboBox == null) return;

 

    // Retrieve the current DataRow

    var dataRow = FindParent<DataGridRowControl>(comboBox);

    if (dataRow == null) return;

 

    var record = dataRow.DataContext;

    if (record == null || record is not PersonModel person)

        return;

 

    int staffId = person.StaffId;

 

    string fullName = person.ClientName;

 

    // Assuming the DataContext of the ComboBox is a collection of staff or similar

    var dataContextItems = comboBox.DataContext as IEnumerable<object>;

    if (dataContextItems == null) return;

 

    // Filter items where the staffId matches

    var filteredItems = dataContextItems

        .OfType<ClientModel>() // Replace with your actual item type

        .Where(item => item.Id == staffId) // Adjust property name as neeqaded

        .ToList();

    if (filteredItems.Count > 0)

        comboBox.ItemsSource = filteredItems;

 

    // Split the names by "-" and trim whitespace

    var names = fullName.Split('-')

                        .Select(name => name.Trim())

                        .ToList();

 

    // Match against your available list (filteredItems or full list)

    var matchedClients = filteredItems

        .Where(client => names.Contains(client.FullName))

        .ToList();

 

    if (matchedClients.Count > 0)

    {

        foreach (var item in matchedClients)

        {

            comboBox.SelectedItems.Add(item);

        }

    }

 

}

 

public static T FindParent<T>(DependencyObject child) where T : DependencyObject

{

    DependencyObject parentObject = VisualTreeHelper.GetParent(child);

    if (parentObject == null) return null;

 

    if (parentObject is T parent)

        return parent;

 

    return FindParent<T>(parentObject);

}


Find the sample in the attachment and let us know if you have any concerns on this.

If this post is helpful, please consider Accepting it as the solution so that other members can locate it more quickly.




Attachment: Sample_bfad2c.zip

Marked as answer

AS Alfred Smith replied to Sweatha Bharathi August 5, 2025 01:01 PM UTC

Hi sorry for the late reply, that sort of put me on the right track. I am having an issue though when i open double click a cell and it creates the combo box, it automatically calls the following event which is meant to go through all the clients and tick those are currently assigned to the staff in the database. 

For some reason this line of code doesn't seem to do anything:

comboBox.SelectedItems.Add(item);


private void OnLoaded(object sender, RoutedEventArgs e)
{
    firstTimeLoaded = true; //in my selection changed event i check this, if true it will stop it from doing anything


    var comboBox = sender as SfComboBox;
    if (comboBox == null)
    {
        return;
    }


    // Retrieve the current DataRow
    var dataRow = FindParent<DataGridRowControl>(comboBox);
    if (dataRow == null)
    {
        return;
    }


    var record = dataRow.DataContext;
    if (record == null || record is not StaffViewModel staff)
    {
        return;
    }


    
    int staffId = staff.Id;
    string fullName = staff.SelectedClientsText;


    List<ClientViewModel> filteredItems = ViewModel.ClientList
            .Where(item => item.Id == staffId)
            .ToList();


    if (staff.Clients != null)
    {        
        if (staff.Clients.Count > 0)
        {
            bool itemFound = false;
            foreach (ClientViewModel item in ViewModel.ClientList)
            {
                foreach(ClientViewModel clientVM in staff.Clients)
                {
                    if (clientVM.Id==item.Id)
                    {
                        itemFound = true;
                    }
                }
                if (itemFound)
                {
                    if (comboBox.SelectedItems!=null)
                    {                                               
                        comboBox.SelectedItems.Add(item);
                    }
                    itemFound = false;
                }
            }                        
        }
    }
}



SB Sweatha Bharathi Syncfusion Team August 6, 2025 09:49 AM UTC

Alfred Smith ,

We have reviewed your query. Based on your provided information , it appears that when a cell is double-clicked, the ComboBox's Loaded event is triggered. In this event, we retrieve the DataRow value for a specific column and match it with the ComboBox's DataContext items. Once a match is found, the corresponding item is set in the SelectedItems property of the ComboBox. This approach ensures that when the ComboBox dropdown is opened, the relevant item is maintained as the selected item of ComboBox.

Additionally, if multiple selections are done based on the names in the DataRow, the SelectedItems are updated each time the ComboBox is loaded. This helps maintain the selected state consistently—whether the selection is made manually or updated at runtime.

Without implementing this approach, the selected items in the ComboBox are not maintained when the dropdown is opened.


AS Alfred Smith replied to Sweatha Bharathi August 7, 2025 03:00 PM UTC

Hi I am getting this strange behavior whenever I click (single click) on the cell. It changes my button to this which it appears to be getting from a field of my Staff view model called Shifts. If I search for "Shifts:" in my code it returns no result. 

 


I am wondering whether the following code is triggering this:

private void OnClick(object sender, RoutedEventArgs e)
{    
    var visualContainer = MainDataGrid.GetVisualContainer();
    if (visualContainer != null && MainDataGrid.SelectionController != null && MainDataGrid.SelectionController.CurrentCellManager != null)
    {
        var rowColumnIndex = visualContainer.PointToCellRowColumnIndex(lastMousePosition);
         if (rowColumnIndex != null)
        {            
            MainDataGrid.MoveCurrentCell(rowColumnIndex);
        }
        MainDataGrid.SelectionController.CurrentCellManager.BeginEdit();
    }
}



SB Sweatha Bharathi Syncfusion Team August 8, 2025 06:45 AM UTC

Alfred Smith,

We have created a new forum for your last update since this is a new query. We request that you have a further follow-up on a new forum.

Note: If you have a new query, please create a new forum.

Loader.
Up arrow icon