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
Image 2 - After click on the button
- 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:
- 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?
- This information will help us proceed further and provide an accurate solution.
- Yes after selection and the combox is closed the button should reappear
- 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.
- The button should only be shown after the selection has been made and the Combobox is closed
- I have the button placed in the Cell Template and the ComboBox in the EditTemplate
- 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.
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(); } } { 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
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;
}
}
}
}
}
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();
}
}
- 7 Replies
- 2 Participants
- Marked answer
-
AS Alfred Smith
- Jul 18, 2025 10:20 AM UTC
- Aug 8, 2025 06:45 AM UTC