Reputation: 782
I have a WPF DataGrid that I am filling using
var allLines = from Lines in ctx.InvoiceLines join PerPs in ctx.ProductsViews on Lines.ProductCode equals PerPs.ProductCode
where (Lines.BranchNo == BrNo) && (Lines.Docket == Docket)
select new { Lines.ProductCode, Lines.Description, Lines.Inv_Quantity, Lines.Grn_Quantity,
Lines.Inv_Price,Lines.Grn_Price,Lines.Inv_Total, Lines.Grn_Total, Lines.AnalCode,
Lines.Vat_Rate, Lines.GrnNo,Lines.Comment , PerPs.OuterUnits};
dgGrid.ItemsSource = allLines;
I want to use two way binding to update the database when any of the values are changed or when a new row is added. Is that possible?
My xaml code is
<DataGrid Grid.Row="3" x:Name="dgGrid" DataContext="{Binding}" FontSize="16" HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible" SelectionUnit="FullRow" SelectionMode="Extended" AutoGenerateColumns="False"
SelectionChanged="dgGrid_SelectionChanged" >
<DataGrid.Columns>
<DataGridTextColumn Width="Auto" Header="ProductCode" Binding="{Binding ProductCode, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="250" Header="Description" Binding="{Binding Description, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" FontSize="14"/>
<DataGridTextColumn Width="61" Header="Inv_Quantity" Binding="{Binding Inv_Quantity, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="63" Header="Grn_Quantity" Binding="{Binding Grn_Quantity, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="59" Header="Inv_Price" Binding="{Binding Inv_Price, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="61" Header="Ord_Price" Binding="{Binding Grn_Price, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="72" Header="Inv_Total" Binding="{Binding Inv_Total, Converter={StaticResource Currency}, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="74" Header="Grn_Total" Binding="{Binding Grn_Total, Converter={StaticResource Currency}, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="58" Header="AnalCode" Binding="{Binding AnalCode, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="40" Header="Vat_Rate" Binding="{Binding Vat_Rate, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="Auto" Header="GrnNo" Binding="{Binding GrnNo, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="Auto" Header="Comment" Binding="{Binding Comment, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="Auto" Header="PerP" Binding="{Binding OuterUnits}" IsReadOnly="True"/>
</DataGrid.Columns>
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightSteelBlue"/>
</DataGrid.Resources>
</DataGrid>
When I run this code all but the PerP column is empty.
I'm quite lost as to how to do the best way so any help will be very much appreciated.
Upvotes: 3
Views: 24809
Reputation: 2868
All the Bindings
for your DataGridTextColumn
besides the "PerP" column are specifying the path twice. For example:
<DataGridTextColumn Width="Auto" Header="ProductCode" Binding="{Binding ProductCode, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
Here your Binding
is first specifying the path to be "ProductCode" and then also specifying it to be "IsSelected". Since there is no "IsSelected" property on the objects in the collection that you are binding to the grid, if you run this under the debugger you should see binding errors in the Output window. If you remove the Path=IsSelected
for those bindings then the column values should be bound correctly.
Your datasource is a collection of an anonymous type so the var
is necessary, but as others have said two-way binding to that collection isn't going to work for updates back to the source.
Upvotes: 4
Reputation: 16618
If the "allLines" variable is a DataTable
, you could just set your DataGrid's AutoGenerateColumns
to true.
You also need not to use the "DataContext" property, but "ItemsSource" instead.
Something like this:
<DataGrid ItemsSource="{Binding Path=allLines.DefaultView}" ... />
To update back the database on changes, call the Update()
method of your datatable, on a "Save" button click for example.
If "allLines" is not a DataTable, then remove this hellish "var" keyword and tell us the true nature of the variable =)
Upvotes: 2
Reputation: 32715
Your allLines
variable is an enumerable of an anonymous type. In C# anonymous types are read-only - the properties cannot be edited, and the changes can't be saved.
Try making your query:
var allLines =
from Lines in ctx.InvoiceLines
join PerPs in ctx.ProductsViews on Lines.ProductCode equals PerPs.ProductCode
where (Lines.BranchNo == BrNo) && (Lines.Docket == Docket)
select Lines;
dgGrid.ItemsSource = allLines.ToList();
Upvotes: 2