I have 3 ComboBoxes in a DevExpress Datagrid Columns namely; Country, Provinces Districts respectively. The Country Column has a dropdown that lists all of the Countries in the World, the Province Dropdown has all of the Provinces in all the Countries, the District dropdown has all of the districts in all the Provinces. Now I want to make it work properly, What I wanted is to display only the the provinces of the selected Country in the Provinces dropdowns and to display only the districts of the selected province in the districts dropdowns. How can I achieve that?
Here is my DATABASE SCRIPT i used and
Here are my codes:
MainWindow.xaml:
<dx:ThemedWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:DataGridBindingExampleCore"
xmlns:conveters="clr-namespace:DataGridBindingExampleCore.Converters"
x:Class="DXApplication2.MainWindow"
Title="MainWindow" Height="800" Width="1000" DataContext="{DynamicResource vm}">
<Window.Resources>
<vm:MainWindowViewModel x:Key="vm" />
<conveters:ConvProvinceID x:Key="ConvProvinceID" />
<conveters:ConvDistrictID x:Key="ConvDistrictID" />
</Window.Resources>
<DockPanel>
<dxg:GridControl Width="990" ItemsSource="{Binding SelectedStudent.PlacesOfInterest}">
<dxg:GridControl.View>
<dxg:TableView/>
</dxg:GridControl.View>
<dxg:GridColumn FieldName="ID" IsSmart="True"/>
<dxg:GridColumn FieldName="StudentID" IsSmart="True"/>
<dxg:GridColumn FieldName="CountryName" IsSmart="True">
<dxg:GridColumn.EditSettings>
<dxe:ComboBoxEditSettings ItemsSource="{Binding Countries}"
DisplayMember="CountryName"
ValueMember="CountryName"/>
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
<dxg:GridColumn FieldName="ProvinceID" IsSmart="True">
<dxg:GridColumn.EditSettings>
<dxe:ComboBoxEditSettings ItemsSource="{Binding Provinces}"
DisplayMember="ProvinceName"
ValueMember="ProvinceID"/>
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
<dxg:GridColumn FieldName="DistrictID" IsSmart="True">
<dxg:GridColumn.EditSettings>
<dxe:ComboBoxEditSettings ItemsSource="{Binding Districts}"
DisplayMember="DistrictName"
ValueMember="DistrictID"/>
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
</dxg:GridControl>
</DockPanel>
</dx:ThemedWindow>
```**MainWindowViewModel.cs:**
```csharp
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DataGridBindingExampleCore.Models;
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace DataGridBindingExampleCore
{
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
bool isLoading;
[ObservableProperty]
ObservableCollection<StudentsModel> students;
[ObservableProperty]
ObservableCollection<CountriesModel> countries;
[ObservableProperty]
ObservableCollection<ProvincesModel> provinces;
[ObservableProperty]
ObservableCollection<DistrictsModel> districts;
[ObservableProperty]
StudentsModel selectedStudent;
int currentIndex = 0;
[RelayCommand]
private void NavigateStudents(string ButtonName)
{
switch (ButtonName)
{
case "NavigateNextButton":
currentIndex = Math.Min(currentIndex + 1, Students.Count - 1);
break;
case "NavigateBeforeButton":
currentIndex = Math.Max(currentIndex - 1, 0);
break;
default:
break;
}
this.SelectedStudent = Students[currentIndex];
}
public MainWindowViewModel()
{
LoadDataAsync();
}
private async void LoadDataAsync()
{
IsLoading = true;
this.Students = new ObservableCollection<StudentsModel>(await DAL.LoadStudentsAsync());
this.Countries = new ObservableCollection<CountriesModel>(await DAL.LoadCountriesAsync());
this.Provinces = new ObservableCollection<ProvincesModel>(await DAL.LoadProvincesAsync());
this.Districts = new ObservableCollection<DistrictsModel>(await DAL.LoadDistrictsAsync());
this.SelectedStudent = Students.FirstOrDefault();
OnPropertyChanged(nameof(SelectedStudent)); // Notify the UI that SelectedStudent has changed
IsLoading = false;
}
}
}
DAL.cs:
using Dapper;
using DataGridBindingExampleCore.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
namespace DataGridBindingExampleCore
{
public class DAL
{
private static readonly string ConnString = "Data Source=(local);Initial Catalog=CollegeDB;Integrated Security=True";
public static async Task<List<StudentsModel>> LoadStudentsAsync()
{
using (IDbConnection conn = new SqlConnection(ConnString))
{
var students = (await conn.QueryAsync<StudentsModel>("SELECT * FROM Students")).ToList();
var allPlacesOfInterest = (await conn.QueryAsync<PlacesOfInterest>("SELECT * FROM PlacesOfInterest")).ToList();
foreach (var student in students)
{
var placesOfInterest = allPlacesOfInterest.Where(p => p.StudentID == student.StudentID).ToList();
student.PlacesOfInterest = new ObservableCollection<PlacesOfInterest>(placesOfInterest);
}
return students;
}
}
public static async Task<List<CountriesModel>> LoadCountriesAsync()
{
using (IDbConnection conn = new SqlConnection(ConnString))
{
var result = await conn.QueryAsync<CountriesModel>("SELECT * FROM Countries");
return result.ToList();
}
}
public static async Task<List<ProvincesModel>> LoadProvincesAsync()
{
using (IDbConnection conn = new SqlConnection(ConnString))
{
var result = await conn.QueryAsync<ProvincesModel>("SELECT * FROM Provinces");
return result.ToList();
}
}
public static async Task<List<DistrictsModel>> LoadDistrictsAsync()
{
using (IDbConnection conn = new SqlConnection(ConnString))
{
var result = await conn.QueryAsync<DistrictsModel>("SELECT * FROM Districts");
return result.ToList();
}
}
}
}
Models (I have combined them here but they are in different files):
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
namespace DataGridBindingExampleCore.Models
{
public partial class PlacesOfInterest : ObservableObject
{
[ObservableProperty]
int iD;
[ObservableProperty]
int studentID;
[ObservableProperty]
string countryName;
partial void OnCountryNameChanged(string oldValue, string newValue)
{
this.ProvinceID = 0;
}
[ObservableProperty]
int provinceID;
partial void OnProvinceIDChanged(int oldValue, int newValue)
{
this.DistrictID = 0;
}
[ObservableProperty]
int districtID;
}
public partial class StudentsModel : ObservableObject
{
[ObservableProperty]
int studentID;
[ObservableProperty]
string studentName;
[ObservableProperty]
ObservableCollection<PlacesOfInterest> placesOfInterest;
}
public partial class CountriesModel : ObservableObject
{
[ObservableProperty]
string countryName;
}
public partial class ProvincesModel : ObservableObject
{
[ObservableProperty]
string countryName;
[ObservableProperty]
int provinceID;
[ObservableProperty]
string provinceName;
}
public partial class DistrictsModel : ObservableObject
{
[ObservableProperty]
int provinceID;
[ObservableProperty]
int districtID;
[ObservableProperty]
string districtName;
}
}