datagrid column does not update - wpf

I have a WPF form with a DataGrid. This DG contains a DataGridTemplateColumn that contains a ComboBox. When I click on the new row of the DG and selected a value from the Combobox and then tab to the next column, the selected value does not stay visible in the combobox column.
However, when I tab back, the correct value shows in the combobox.
How do I keep the selected value showing in the combobox column when I tab off the column?
Here is my comboxbox column xaml:
<DataGridTemplateColumn Header="Type" Width="160">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding LocationType.Description, Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox Name="cboAddrtype"
ItemTemplate="{StaticResource dtAddrType}" IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}, AncestorLevel=1}, Path=DataContext.LocationTypesObject, Mode=OneTime}"
SelectedItem="{Binding Path=SelectedLocationType, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
SelectedValue="{Binding Path=LocationTypeKey, Mode=TwoWay}"
SelectedValuePath="InternalKey"
Width="100" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

In CellTemplate you're binding LocationType.Description and in CellEditingTemplate you're binding SelectedLocationType and LocationTypeKey. I'm not sure that your binding from ComboBox won't somehow affect LocationType.Description.
Furthermore, SelectedLocationType and LocationTypeKey are not in the context of DataTemplate. You should add a Source binding property to get your ViewModel.

Related

Binding between two DataTemplate works in one direction only

I have a DataGrid where there are Date0, Date1, and Date2 columns. I can change the columns with a ComboBox.
I started to use DataTemplate. The CellTemplate uses Date0InParameterEditingTemplate where I bind Date0 which is not simple DateTime but a class. Then this class is bound to DateEditingTemplate. I would like to use DateEditingTemplate later with Date1 and Date2 as well.
The data goes well to one direction, so the ComboBox displays the proper date. When I select a new value in the ComboBox then the SelectedItem changes. But the content of ContentControl remains unchanged.
<DataGridTemplateColumn Header="{x:Static r:Resource.Date0}"
CellTemplate="{StaticResource Date0InParameterEditingTemplate}"/>
<DataTemplate x:Key="DateEditingTemplate">
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type DataGrid}}, Path=DataContext.ValidDateObjects}"
SelectedItem="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Date" Style="{StaticResource ComboBoxError}" IsEditable="False"
ItemStringFormat="{StaticResource DateFormatHU}" />
</DataTemplate>
<!--<DataTemplate x:Key="DateEditingTemplate">
<TextBlock Text="{Binding Date}"/>
</DataTemplate>-->
<DataTemplate x:Key="Date0InParameterEditingTemplate">
<ContentControl Content="{Binding Date0, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ContentTemplate="{StaticResource DateEditingTemplate}"/>
</DataTemplate>

WPF Datagrid MouseBinding MVVM

I managed to handle a double click on one of my datagrid rows to execute a command on my viewmodel by this xaml:
This works perfect when I click somewhere in the area of the first column (which is bound to the readonly ID), but fails when the double click is done in the area of the textbox in column two (CustomerNumber, which of course catches the doubleclick).
Which would be a MVVM-like way to handle doubleclicks for both scenarios?
You could replace the DataGridTextColumn with a DataGridTemplateColumn and add a MouseBinding to the TextBox in the CellEditingTemplate:
<DataGridTemplateColumn Header="Customer Number">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CustomerNumber}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding CustomerNumber}">
<TextBox.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</TextBox.InputBindings>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Binding data grid template column combo box's selected item to data grid text column

In my project I've a data grid which contains template columns (combobox)and data grid text columns.How can i bind a data grid text column to a property in the selected item of the combobox in the template column.
for example, The first column is a template column that contains a combobox and the next column is a regular data grid text column. How can i bind the text column text to a property in the selected item of the combobox in the template column.
I've tried this but is giving binding error
<DataGrid
Grid.Column="0"
Grid.Row="3"
Grid.ColumnSpan="9"
AutoGenerateColumns="False"
Margin="5"
CanUserDeleteRows="False" CanUserAddRows="False"
DataContext="{Binding}"
IsEnabled="{Binding EnableControls}"
ItemsSource="{Binding SalesItemCollection}"
EnableRowVirtualization="False"
EnableColumnVirtualization="False"
IsSynchronizedWithCurrentItem="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Batch" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="comboBox"
IsEditable="True"
MaxDropDownHeight="125"
DisplayMemberPath="BatchName"
VerticalAlignment="Stretch"
VerticalContentAlignment="Center"
IsSynchronizedWithCurrentItem="False"
SelectedValuePath="BatchId"
SelectedValue="{Binding BatchId}"
SelectedItem="{Binding Batch}"
ItemsSource="{Binding Path=DataContext.BatchColection,
RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn IsReadOnly="True" Header="Expiry "
Binding="{Binding ElementName = comboBox, Path=SelectedItem.Expirydate}" />
</DataGrid.Columns>
I've tried changing Binding ElementName = comboBox to Binding Source={x:Reference comboBox}. But it is throwing exception.
Can anyone tell me a solution for this.
As you are already binding selected Item to Batch use that, Try this
<DataGridTextColumn IsReadOnly="True" Header="Expiry "
Binding="{Binding Source=Batch, Path=Title}" />

WPF Datagrid TemplateColumn Control Enable and Disable

I have Datagrid with two TemplateColumn.
First column is a Combobox and Second column with Extended IntergerUpDown control
I need to Enable/Disable the IntegerUpDown control based on the Combox box SelectedItem value.
Please help me how to accomplish this. Sample xaml below.
<Grid><DataGrid ItemsSource="{Binding List1}" Name="x1">
<DataGrid.Columns>
<DataGridTemplateColumn Header="ColorTemplate">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.List2, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}"
DisplayMemberPath="Name" SelectedValue="{Binding ColourId}" SelectedValuePath="Id" Tag="{Binding Id}"
HorizontalAlignment="Stretch" x:Name="discussTemplate" VerticalAlignment="Stretch"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="UPDown" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<extToolkit:IntegerUpDown AllowSpin="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Minimum="0"
x:Name="updown"
IsEnabled="????" >
</extToolkit:IntegerUpDown>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
This can be easily done with a DataTrigger on your ViewModel ColourId property.
As your SelectedValue property on the ComboBox is already binded, you can have a DataTrigger on your extToolkit:IntegerUpDown control that will set IsEnabled to True/False based on ColourId value on your ViewModel.

WPF Data Binding ComboBox in DataGridTemplateColumn

I have a DataGrid and I want to populate a column that contains a ComboBox with a dynamic ItemsSource of elements, based on the row. I have the combo box display correctly, and the correct list of elements are populated in the list, as pulled in from the AvailableLogFileProcessTypes property, which is a ReadOnlyCollection. However, when the selection is made by the user in the combobox, the LogFileProcessType property is not set to the selection.
Data:
Property LogFileDirectories, IEnumerable<LogFileData>,
LogFileData:
public LogFileProcessType LogFileProcessType{get;set;}
public ReadOnlyCollection<LogFileProcessType> AvailableLogFileProcessTypes { get; set; }
The property currently has a backing field, and the breakpoint in the set property does not get hit, so I know it is localized to the binding setup. What is wrong with my XAML that is preventing the property from being set?
As you can see, I've tried setting both the SelectedValue and SelectedItem in the CellEditingTemplate and the CellTemplate. I am not sure which of these is appropriate.
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=LogFileDirectories, UpdateSourceTrigger=PropertyChanged}"
HeadersVisibility="Column" CanUserReorderColumns="False" CanUserAddRows="False" Margin="0,0,0,35" Grid.RowSpan="3">
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Processed" Binding="{Binding Path=IsProcessingComplete, Mode=OneWay}" Width="70" IsReadOnly="True" />
<DataGridTemplateColumn Header="template">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Path=LogFileProcessType, Mode=TwoWay}"
SelectedItem="{Binding Path=LogFileProcessType, Mode=TwoWay}"
ItemsSource="{Binding Path=AvailableLogFileProcessTypes}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Path=LogFileProcessType, Mode=TwoWay}"
SelectedItem="{Binding Path=LogFileProcessType, Mode=TwoWay}"
ItemsSource="{Binding Path=AvailableLogFileProcessTypes}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
See Damascus response for thought process.
Need to Specify UpdateSourceTrigger on CellTemplate / CelLEditTemplate. This triggers the property change.
<DataGridTemplateColumn Header="template">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Path=LogFileProcessType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Path=AvailableLogFileProcessTypes}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Path=LogFileProcessType, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Path=AvailableLogFileProcessTypes}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Try to add this to your ComboBox :
<ComboBox SelectedValue="{Binding Path=LogFileProcessType, Mode=TwoWay}"
SelectedItem="{Binding Path=LogFileProcessType, Mode=TwoWay}"
ItemsSource="{Binding Path=AvailableLogFileProcessTypes, UpdateSourceTrigger=PropertyChanged}"/>
Therefore, with an UpdateSourceTrigger set to PropertyChanged, each time the object AvailableLogFileProcessTypes will change and call OnPropertyChanged, the ItemsSource will be refreshed.

Resources