I have a xamdatagrid. I have added 2 combo box fields in xamdatagrid.
The item source for 2nd combo box should be set based on 1st combo box selection.
In the below example, I need to show books based on branch selection from branch combo box field.
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ig:XamDataGrid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" GroupByAreaLocation="None" DataSource="{Binding Employees, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, Mode=TwoWay}" BorderBrush="Black" BorderThickness="0.5" AutoFit="True"> <ig:XamDataGrid.FieldSettings> <ig:FieldSettings AllowRecordFiltering="True" /> </ig:XamDataGrid.FieldSettings> <ig:XamDataGrid.FieldLayoutSettings> <ig:FieldLayoutSettings HighlightAlternateRecords="True" AutoGenerateFields="False" AutoFitMode="ExtendLastField" /> </ig:XamDataGrid.FieldLayoutSettings> <ig:XamDataGrid.FieldLayouts> <ig:FieldLayout> <ig:Field Name="Name" Label="Default Name" Width="InitialAuto"> <ig:Field.Settings> <ig:FieldSettings AllowEdit="False"/> </ig:Field.Settings> </ig:Field> <ig:ComboBoxField Name="Branches" Label="Branch" BindingType="Unbound" > <ig:Field.Settings> <ig:FieldSettings EditorType="{x:Type igEditors:XamComboEditor}" > <ig:FieldSettings.EditorStyle> <Style TargetType="{x:Type igEditors:XamComboEditor}"> <Setter Property="ItemsSource" Value="{Binding Path=DataContext.Branches, RelativeSource={RelativeSource AncestorType={x:Type ig:XamDataGrid}} ,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <Setter Property="DisplayMemberPath" Value="Name"> </Setter> <Setter Property="SelectedItem" Value="{Binding DataItem.SelectedBranch}"> </Setter> </Style> </ig:FieldSettings.EditorStyle> </ig:FieldSettings> </ig:Field.Settings> </ig:ComboBoxField> <ig:ComboBoxField Name="Books" Label="Book" BindingType="Unbound" > <ig:Field.Settings> <ig:FieldSettings EditorType="{x:Type igEditors:XamComboEditor}" > <ig:FieldSettings.EditorStyle> <Style TargetType="{x:Type igEditors:XamComboEditor}"> <Setter Property="ItemsSource" Value="{Binding Path=DataContext.Books, RelativeSource={RelativeSource AncestorType={x:Type ig:XamDataGrid}} ,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <Setter Property="DisplayMemberPath" Value="Name"> </Setter> <Setter Property="SelectedItem" Value="{Binding DataItem.SelectedBook}"> </Setter> </Style> </ig:FieldSettings.EditorStyle> </ig:FieldSettings> </ig:Field.Settings> </ig:ComboBoxField> </ig:FieldLayout> </ig:XamDataGrid.FieldLayouts> </ig:XamDataGrid> </Grid>
Sample proj
WpfApp3.zip
Hello Yugandhar,
In order to use a custom object instead of primitive data type, you need to change two things, the way the converter works and the binding.
In the converter you need to work with the values as an object of that class and then just like with string the Name property of the UnitCategory is checked and different Unit collection is returned based on it.
It’s a little bit trickier with the binding, since the regular Field is not recognizing the values of the Name parameter for the UnitCategory, meaning that if you leave the binding as it is now it will behave as a regular text field. To make it behave as a ComboBoxField, what you need to do is to either change it as ComboBoxField or leave it as a Field and add EditorType and set it to XamComboEditor. Below you can see both approaches:
<igWPF:Field Name="UnitCategory" EditorStyle="{StaticResource UnitCategoryStyle}" EditorType="{x:Type igEditors:XamComboEditor}"/>
<igWPF:ComboBoxField Name="UnitCategory" >
<igWPF:Field.Settings>
<igWPF:FieldSettings EditorStyle="{StaticResource UnitCategoryStyle}"/>
</igWPF:Field.Settings>
</igWPF:ComboBoxField>
To be easier to determine the changes I have left the old code commented out so you can compare the changes.
I am attaching a modified version of the sample, please test it on your side and let me know if you have any questions.
Regards, Ivan Kitanov
ComboBoxFieldBasedOnOtherComboBoxField_modified2.zip
Thanks Ivan for providing answers to my queries.
I understand the code. I am unable bind the unit category after I change the type from string to custom class.
Where could be the problem.
<Grid> <Grid.Resources> <local:ComboSourceConverter x:Key="cscconv" /> <Style x:Key="UnitCategoryStyle" TargetType="{x:Type igEditors:XamComboEditor}"> <Setter Property="ItemsSource" Value="{Binding Path=DataContext.UnitCategories, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" /> <Setter Property="SelectedItem" Value ="{Binding Path=DataItem.UnitCategory}" /> <Setter Property="DisplayMemberPath" Value="Name" /> </Style> <Style x:Key="UnitStyle" TargetType="{x:Type igEditors:XamComboEditor }"> <Setter Property="ItemsSource" Value="{Binding Path=DataItem.UnitCategory, Converter={StaticResource cscconv}}" /> </Style> </Grid.Resources> <igWPF:XamDataGrid DataSource="{Binding data}" CellChanged="XamDataGrid_CellChanged"> <igWPF:XamDataGrid.FieldLayoutSettings> <igWPF:FieldLayoutSettings AutoGenerateFields="False" /> </igWPF:XamDataGrid.FieldLayoutSettings> <igWPF:XamDataGrid.FieldLayouts> <igWPF:FieldLayout> <igWPF:FieldLayout.Fields> <igWPF:Field Name="Item"></igWPF:Field> <igWPF:Field Name="UnitCategory"> <igWPF:Field.Settings> <igWPF:FieldSettings EditorStyle="{StaticResource UnitCategoryStyle}" /> </igWPF:Field.Settings> </igWPF:Field> <igWPF:Field Name="Unit"> <igWPF:Field.Settings> <igWPF:FieldSettings EditorStyle="{StaticResource UnitStyle}" /> </igWPF:Field.Settings> </igWPF:Field> </igWPF:FieldLayout.Fields> </igWPF:FieldLayout> </igWPF:XamDataGrid.FieldLayouts> </igWPF:XamDataGrid> </Grid>
Here is view model & model
public class ViewModel : INotifyPropertyChanged { public ObservableCollection<DataModel> data { get; set; } public List<UnitCategory> UnitCategories { get; set; } public static List<string> WeightUnits { get; set; } public static List<string> DistanceUnits { get; set; } public ViewModel() { this.data = new ObservableCollection<DataModel>(); this.UnitCategories = new List<UnitCategory>(); UnitCategory u1 = new UnitCategory(); u1.Name = "Wt"; UnitCategory u2 = new UnitCategory(); u2.Name = "Dt"; this.UnitCategories.Add(u1); this.UnitCategories.Add(u2); WeightUnits = new List<string>() { "mg", "g", "kg" }; DistanceUnits = new List<string>() { "cm", "m", "km" }; DataModel data1 = new DataModel(); data1.Item = "Item 1"; DataModel data2 = new DataModel(); data2.Item = "Item 2"; this.data.Add(data1); this.data.Add(data2); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public class DataModel { public string Item { get; set; } public UnitCategory UnitCategory { get; set; } public string Unit { get; set; } public DataModel() { } } public class UnitCategory { public string Name { get; set; } }
In order to show an empty unit selection instead of the old value, I suggest you using the CellChanged event of the XamDataGrid and set the value of the “Unit” cell to empty string in the same record where the CellChanged event occurred. To make the sample simpler I have changed the FieldSetting of the two ComboBoxFields, instead of providing CellValuePresenter, EditorStyle is set, which has the same properties and values set as the CellValuePresenter.
While running the sample, once the user changes the selection inside the UnitCategory, the value of the “Unit” cell would be set to an empty string.
I am attaching a modified version of the sample, please test it on your side and let me if you need further assistance.
ComboBoxFieldBasedOnOtherComboBoxField - modified.zip
Thanks Ivan,
But why I am not able to clear selection of unit field when user changes unit category.
<Style x:Key="cvp1" TargetType="{x:Type igWPF:CellValuePresenter}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type igWPF:CellValuePresenter}"> <igEditors:XamComboEditor SelectedItem="{Binding DataItem.Unit, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Path=DataItem.UnitCategory, Converter={StaticResource cscconv}}"> </igEditors:XamComboEditor> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="cvp2" TargetType="{x:Type igWPF:CellValuePresenter}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type igWPF:CellValuePresenter}"> <igEditors:XamComboEditor SelectedItem="{Binding DataItem.UnitCategory, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Path=DataContext.UnitCategories, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"> </igEditors:XamComboEditor> </ControlTemplate> </Setter.Value> </Setter> </Style>
I used 2 way binding. The problem is after unit category change -> unit shows old value. Unit selection should be empty.
In order to set the ItemSource of a ComboBoxField based on another ComboBoxField, a custom style needs to be created, it should target the CellValuePresenter and with the help of converter the ItemSource of the list is determined based on what value is selected from the ComboBoxField responsible for the ItemSource changing.
I am sending a small sample, which demonstrates what I have described above. The sample consists of a XamDataGrid with 3 fields, Item, UnitCategory and Unit. The UnitCategory field is the field that the Unit field is based on, when the user selects an item from the UnitCategory field the ItemSource of the Unit field is changing. The change is done through converter (ComboSourceConverter class), which takes the value of the UnitCategory and based on it the ItemSource is set. For example, it the UnitCategory is Distance the values for the Unit field are (cm, m and km) if it is set to Weight the values are (mg, g and kg). The Styles are set for each ComboBoxField and it the style of the Unit field for ItemSource is used the value of the UnitCategory field for the corresponding row, which is being converted by the converter.
To adapt this example to the sample you provided I can suggest you to split the List of Book objects to different lists for each category and then to add an overridden ToString() method that returns the Name property for the Book and Branch classes in order to display them correctly inside the field of the grid when they are converted.
Please let me know if you have any questions.
ComboBoxFieldBasedOnOtherComboBoxField.zip