Confusion with DataGridComboboxFIeld

Dear Community!

I am confused with the Comboboxfield for the DataGrid. I want to use the List Usernames as the Datasource to pick from to the set the responsible person Property in the WorkDisplayViewModel class. However, as soon as i have picked a person and unfocus the Combobox, the Value is directly set to its original value again. Where does this come from? Secondly i wanted to display Enum values to choose for the Priority, however, i do not even get anything inside the Combobox for the enum values. What am i doing wrong?

The DataGrid:

<dataGrid:SfDataGrid.Columns>
<dataGrid:DataGridComboBoxColumn HeaderText="Responsible Person"
MappingName="ResponsiblePerson"
DisplayMemberPath="name"
ItemsSource="{Binding Usernames}"/>
<dataGrid:DataGridTextColumn MappingName="Description" HeaderText="Description"
CellTextAlignment="Center"
HeaderTextAlignment="Center"/>
<dataGrid:DataGridComboBoxColumn MappingName="Priority" HeaderText="Priority"
ItemsSource="{Binding Priorities}"
CellTextAlignment="Center"
HeaderTextAlignment="Center"/>

</dataGrid:SfDataGrid.Columns>
</dataGrid:SfDataGrid>


The ViewModel of the page:

public partial class VehicleDetailsViewModel : BaseViewModel
{
// == observable properties ==
[ObservableProperty]
private VehicleDisplayViewModel vehicle;

[ObservableProperty]
private ObservableCollection<VehicleDisplayViewModel> vehicleForDisplay;

[ObservableProperty]
private bool propertyUpdated;

[ObservableProperty]
private AddWorkModel workToAdd;

[ObservableProperty]
private ObservableCollection<UserNameResponse> usernames;

[ObservableProperty]
private bool isAddWorkPopupOpen;

[ObservableProperty]
private bool workChanged;

public IEnumerable<Priorities> Priorities { get; set; }


// == private fields ==
private VehicleTransferObject _vehicleTransferObject;
private readonly VehicleState _vehicleState;
private readonly UserState _userState;
private VehicleDisplayViewModel original;
private readonly WorkState _workState;

// == constructor ==
public VehicleDetailsViewModel(NavigationService navigationService, VehicleTransferObject vehicleTransferObject, VehicleState vehicleState,
UserState userState, WorkState workState) : base(navigationService)
{
Priorities = Enum.GetValues(typeof(Priorities)).Cast<Priorities>();

_vehicleState = vehicleState;
_workState = workState;
_userState = userState;
_userState.UserNamesReceived += (sender, list) => Usernames = new ObservableCollection<UserNameResponse>(list);
_userState.GetAllUsernames();

_vehicleTransferObject = vehicleTransferObject;
original = new VehicleDisplayViewModel(_vehicleTransferObject.VehicleDisplayViewModel);
_vehicleTransferObject.VehicleDisplayViewModel.PropertyChanged += VehicleDisplayViewModelOnPropertyChanged;
Vehicle = vehicleTransferObject.VehicleDisplayViewModel;
VehicleForDisplay = new ObservableCollection<VehicleDisplayViewModel>();
VehicleForDisplay.Add(Vehicle);

Vehicle.Works.ToList().ForEach(t => t.PropertyChanged += WorkPropertyChanged);

WorkToAdd = new AddWorkModel();
}

// == relay commands ==
[RelayCommand]
public async Task UpdateWorks()
{
List<WorkDisplayViewModel> toChange = Vehicle.Works.Where(f => !f.Equals(f.Original)).ToList();

await Task.WhenAll(toChange.Select(async t =>
{
await _workState.UpdateWork(t.Identifier, new WorkRequest()
{
description = t.Description,
priority = t.Priority,
responsiblePerson = t.ResponsiblePerson,
vehicleIdentifier = t.VehicleIdentifier
});

t.Original = new WorkDisplayViewModel(t);

await GetWorks();
}));

}

[RelayCommand]
public async Task OpenAddWorkPopup()
{
IsAddWorkPopupOpen = true;
}

[RelayCommand]
public async Task UpdateVehicle()
{
await _vehicleState.UpdateVehicle(Vehicle.Identifier, new VehicleRequest()
{
number = Vehicle.Number,
type = Vehicle.Type,
status = Vehicle.Status,
stand = Vehicle.Stand,
priority = Vehicle.Priority
});

PropertyUpdated = false;
}

[RelayCommand]
public async Task AddWork()
{
WorkRequest request = new WorkRequest()
{
description = WorkToAdd.Description,
priority = WorkToAdd.Priority,
responsiblePerson = WorkToAdd.ResponsiblePerson,
vehicleIdentifier = Vehicle.Identifier
};

await _workState.AddWork(request);
GetWorks();
}

// == public methods ==
public async Task GetWorks()
{
List<WorkDisplayViewModel> works = await _workState.GetWorksForVehicle(Vehicle.Identifier);
Vehicle.Works.AddRange(works.Where(t => Vehicle.Works.All( f => f.Identifier != t.Identifier)));
}
// == private methods ==
private void WorkPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if(sender is not WorkDisplayViewModel work)
return;

WorkChanged = Vehicle.Works.Any(f => !f.Equals(f.Original));
}

private void VehicleDisplayViewModelOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if(sender is not VehicleDisplayViewModel account || e.PropertyName is nameof(VehicleDisplayViewModel.WorkCount))
return;

bool equals = original.Equals(account);

PropertyUpdated = !equals;
}
}


The display viewmodel where i want to set the ResponsiblePerson Property:

ublic partial class WorkDisplayViewModel : BaseDisplayViewModel
{
[ObservableProperty]
private string vehicle;
[ObservableProperty]
private UserNameResponse responsiblePerson;
[ObservableProperty]
private string description;
[ObservableProperty]
private Priorities priority;
[ObservableProperty]
private string createdBy;
[ObservableProperty]
private string updatedBy;

[ObservableProperty]
private WorkDisplayViewModel original;


// == properties ==
public string VehicleIdentifier { get; set; }

// == constructor ==
public WorkDisplayViewModel(WorkResponse response)
{
Vehicle = response.vehicle;
VehicleIdentifier = response.vehicleIdentifier;
Identifier = response.identifier;
ResponsiblePerson = response.responsiblePerson;
Description = response.description;
Priority = response.priority;
CreatedBy = response.createdBy;
UpdatedBy = response.updatedBy;

Original = new WorkDisplayViewModel(this);
}

public WorkDisplayViewModel(WorkDisplayViewModel response)
{
Vehicle = response.Vehicle;
VehicleIdentifier = response.VehicleIdentifier;
Identifier = response.Identifier;
ResponsiblePerson = response.ResponsiblePerson;
Description = response.Description;
Priority = response.Priority;
CreatedBy = response.CreatedBy;
UpdatedBy = response.UpdatedBy;
}

partial void OnResponsiblePersonChanged(UserNameResponse? oldValue, UserNameResponse newValue)
{
Console.WriteLine("t");
}

// == override methods ==
public override bool Equals(object? obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

var other = (WorkDisplayViewModel)obj;

return ResponsiblePerson == other.ResponsiblePerson &&
Description == other.Description &&
Priority == other.Priority &&
CreatedBy == other.CreatedBy &&
UpdatedBy == other.UpdatedBy;
}
}


And the corresponding class:

public class UserNameResponse
{
public string name { get; set; }
public string identifier { get; set; }
}



5 Replies

NY Nirmalkumar Yuvaraj Syncfusion Team February 16, 2024 12:31 PM UTC

Hi Oliver ,


Query

Response

I am confused with the Comboboxfield for the DataGrid. I want to use the List Usernames as the Datasource to pick from to the set the responsible person Property in the WorkDisplayViewModel class. However, as soon as i have picked a person and unfocus the Combobox, the Value is directly set to its original value again. Where does this come from?

As of now, DataGrid does not have support for binding User Defined collection in DataGridComboBox column. We have already considered your request as a feature. We will implement this feature in any of our upcoming releases. At the planning stage for every release cycle, we review all open features and identify features for implementation based on specific parameters including product vision, technological feasibility, and customer interest. We appreciate your patience and understanding until then. You can follow up with the below feedback for further details, 

 

Feedback link: https://www.syncfusion.com/feedback/45786/provide-support-to-bind-user-defined-collection-in-datagridcombobox-column

Secondly i wanted to display Enum values to choose for the Priority, however, i do not even get anything inside the Combobox for the enum values. What am i doing wrong?

Based on the information provided, it appears that the issue you are experiencing is related to type conversion. To resolve this issue, you need to convert the ObservableCollection of enum to IEnumerable<object>. We have attached a simple sample and a code snippet for your reference.

 

Code snippet:

// XAML

<syncfusion:DataGridComboBoxColumn BindingContext="{x:Reference viewModel}"

                        HeaderText="Location" 

                    ItemsSource="{Binding WorkLocationCollection}"

                        ShowClearButton="False"

                    MappingName="Location"/>

 


// ViewModel

private ObservableCollection<WorkLocationType> _workLocationCollection { get; set; } 

public IEnumerable<object> WorkLocationCollection { get; set; }

 

_workLocationCollection = Enum.GetValues(typeof(WorkLocationType)).Cast<WorkLocationType>().ToObservableCollection();

 

WorkLocationCollection = this._workLocationCollection.Select(wt => (object)wt);

 


Regards,

Nirmalkumar



NY Nirmalkumar Yuvaraj Syncfusion Team February 16, 2024 12:34 PM UTC

Oliver,


Please find the sample below.


Regards,

Nirmalkumar




Attachment: SfDataGridSample_ComboBox_cb23bce6.zip


OS Oliver Stöckl replied to Nirmalkumar Yuvaraj February 16, 2024 01:09 PM UTC

I am a bit confused with the first answer you provided as the documentation explicitely states that i can use UserDefined types: "

Collection of user-defined types

To display a list of user-defined items in the drop-down of a combo box, create a DataGridComboBoxColumn and set its ItemsSource property to a user-defined collection. By default, if the DisplayMemberPath is not set, the combo box column will display the values from the MappingName property of the column."

And indeed when i select a specific value of the Combobox it is set correctly as the ResponsiblePerson, however, when i deselect the ComboBox again and select another column, for example, the value is automatically set to null again.



NY Nirmalkumar Yuvaraj Syncfusion Team February 19, 2024 10:02 AM UTC

Hi Oliver,


We have previously provided support for binding the User-defined collection in the Combo box column for the UI. However, editing capabilities were not included in this support. We are pleased to inform you that we have now implemented enhancements to meet your requirements. These enhancements will be included in our upcoming weekly patch release scheduled for February 20, 2024. We will notify you as soon as the release is available, and we sincerely appreciate your patience in the meantime.


Regards,

Nirmalkumar



NY Nirmalkumar Yuvaraj Syncfusion Team February 20, 2024 01:45 PM UTC

Hi Oliver,


We are glad to inform you that the enhancement “Support to edit UserDefined collection in DataGridComboBoxColumn” has been included in our weekly NuGet release. Please update the Syncfusion.Maui.DataGrid package to version 24.2.7


https://www.nuget.org/packages/Syncfusion.Maui.DataGrid


We thank you for your support and appreciate your patience in waiting for this update. Please contact us if you require any further assistance.


Regards,

Nirmalkumar


Loader.
Up arrow icon