I have a DataGrid which is bind to a list like below that has various properties. I have 2 requirements that i am struggling with.
<DataGrid ItemsSource="{Binding Path=VariedObjectList}"
AutoGeneratingColumn="OnAutoGeneratingColumn" x:Name="dataGridView"
SelectionMode="Single" AutoGenerateColumns="true" CanUserAddRows="true" CanUserDeleteRows="true />
How can i achieve this ? I would like to keep the binding to the entire collection itself as in above xaml.
public class VariedObjectList
{
public Modes ModeType { get; set; }
public int Value{ get; set; }
public <dataType??> ValueRange { get; set; } // not sure what should be the type for ValueRange
}
public enum Mode
{
ModeSlow = 0,
ModeFast = 1,
ModeNeutral = 2,
ModeNone = 3
}
I modified the code as suggested by Keith and although most of my changes are working, i have problem in the below areas
(i)i could not get to have the combo box editable working. It takes value when i type in but once my focus leaves the field, the text disappears and binding never happens with 'SelectedValueRange' for text entered. But when there is a list and if i select any value from list, that gets binded to 'SelectedValueRange' but not for text input.
(ii)ModeType being enum, when new row is entered by default i want it to display 'ModeSlow' but its empty. Also, if I update one row, all the previous rows are also updated with the latest value.its behaviour is wierd but i know i am missing something.
public class VariedObjectList : INotifyPropertyChanged
{
public Mode ModeType { get; set; } = Mode.ModeSlow;
private int val;
public int Value {
get { return val; }
set
{
val = value;
OnPropertyChanged("Value");
SetValueRangeList();
}
}
public List<strings> ValueRange { get; set; }
public string SelectedValueRange {get; set;}
}
below is updated xaml
I am setting the ObjectDataProvider for the Enum
<Window.Resources>
<ObjectDataProvider x:Key="EnumProvider" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Modes"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources >
<DataGrid x:Name="dataGridView" Grid.Row="0" DataGridCell.Selected="DataGridGotFocus" ItemsSource="{Binding VariedObjectList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False"
CanUserDeleteRows="true" SelectionMode="Single" CanUserAddRows="True" VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header=" ModeType " >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource EnumProvider}}"
SelectedItem="{Binding Path= ModeType
, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value, UpdateSourceTrigger=LostFocus}"/>
<DataGridTemplateColumn Header="ValueRange" >
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox IsEditable="True" SelectedValue="{Binding SelectedValueRange, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Path= ValueRange }" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedValueRange, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Can someone please point out what am i missing with sample code? Thanks.
Let's start with the VariedObjectList
class:
Since ValueRange
is going to be changing nd you want the UI to update with it, VariedObjectList
is going to have to implement the INotifyPropertyChanged Interface.
The type for ValueRange
can be any generic collection of int
. I would recoomend declaring the property as IList<int>
, because it gives you lots of room to use different collections if you need to.
In ModeType.set
, along with raising PropertyChanged
, you'll need to create or retrieve the list of values you want to display for that Mode
and then assign that list to ValueRange
.
Now for the DataGrid
:
If you want to change the behavior of the ValueRange
column depending on ModeType
, you're going to have to give up AutoGenerateColumns="true"
Instead, you'll explicitly define the columns between <DataGrid.Columns>
tags.
I would recommend DataGridTemplateColumn
for the ValueRange
column. The CellEditingTemplate
would contain a ComboBox
with ItemsSource={Binding ValueRange}
. You can apply a Style
to the ComboBox
that changes IsEditable
depending on the value of ModeType
. This will let you set the ability of the user to enter text which doesn't match any items in the list.
For the editable ComboBox
, you will have to use the Text
property. SelectedValue
and SelectedItem
only work when selecting an item from the drop down, not when entering custom text.