Hi, I am developing a WPF browser application using Linq and your datagrid but I am having major problems trying to delete a record. From looking through various forums and your help I have got to the point where I can retrieve the data usning LINQ and settign the result as the DataSource. I can add a record fine but whenit comes to deleteing I just cant seem to tie it togther. A number of forums have suggesed that once you know what records you need to delete you query it from teh database using LINQ then plase the result into a DeleteOnSubmit command. So I have the following code:
private void datagridMapping_RecordsDeleting(object sender, Infragistics.Windows.DataPresenter.Events.RecordsDeletingEventArgs e)
{
DataCentreDataContext dsMapping = new DataCentreDataContext();
foreach (var rec in datagridMapping.SelectedItems.Records)
try
var mappingres =
from mappingItem in dsMapping.DATAMAPPINGs
where mappingItem.INDEX == rec.???????????????
select mappingItem;
DATAMAPPING delRecord = new DATAMAPPING();
delRecord = (DATAMAPPING)mappingres;
dsMapping.DATAMAPPINGs.DeleteOnSubmit(delRecord);
}
catch (Exception ex)
MessageBox.Show("Error", "Error - " + ex.Message);
dsMapping.SubmitChanges();
I have placed ?????? where I am having the trouble. I guess I may have this very wrong so any help would be very much appreciated.
Regards,
Kevin.
Hello Kevin,
When having a quick look at your code, this is what I notice:
1. The records deleting event arguements expose a collection of the records for deletion as well (e.Records), which is a much more flexible than the SelectedItems.Records collection.
2. Your LINQ query will return an IEnumerable object, so I think you will not be able to cast mappingres to DATAMAPPING, as I believe one is collection and the other not.
3. I think you do not need this LINQ query at all. As you are adding the underlying data business object to the DeleteOnSubmit method, you can do this directly from the DataRecord. Each DataRecord exposes a Dataitem property, which will be your underlying object, in your case DataMapping so you can pass that in the DeleteOnSubmit method directly. Note, that you have to cast the Record to DataRecord, when iterating though the e.Record collection.
Let me know if you have questions on this.
Hi,
I am struggling with the whole concept to be honest. I am new to LINQ and WPF.
I thought the insert was working the code was placed in the RecordUpdated event and worked, but I now get an error when I update an existsing record.
I cant seem to get my gead around how to simply link up a table and the grid to enable simple Add/Edit/Remove functionality.
I dont want to expose all the columns of the tabel to the grid.
Do you have a sample project I may be able to get some idea of what I am dealing with.
Cheers, as awlays.
Kevin,
I have created a small sample with a XamDataGrid bound to a database through LINQ queries. You do not need to handle all the events and look for the modified/deleted records so that you update the back-end databse. What you need is to call the SubmitChanges() method of the context when you need the databse to be updated. LINQ is quite optimized to handle this pretty smoothly.
If you have not exposed all of the fields, you have to be carefull. For example, when you are hiding a field that cannot be null, you have to expose this or at least set this field's value in code behind when adding the record. In the NorthWindDataBase in the Products table, the ProductName cannot be null, and if you will get an exception if you do not set this and commit changes. If you want to set some data (for example for a property of the entity class from a hidden field) you can use the RecordUpdated event and check if the updated record is the CurrentAddRecord. I am going to include this in the sample as well. Editting and removing are pretty straightforward simply by commiting the changes.
I have applied your method and got the grid to populate however one of the reasons I used Linq in the first place was I have a tree view on the right of the grid which contains a set of values. the idea being the user click on a value and the grid is populated with relevent data. I originally used Linq to query the database using the tree view selected value as the where clause.
I guessed the way round this was to programmatically apply a filter instead. I looked at you documentation and tried what it suggested but I get an error when adding the filter:
private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
FieldLayout fieldLayout = datagridMapping.FieldLayouts[0];
// Create a new RecordFilter for 'Country' field.
RecordFilter filter = new RecordFilter();
filter.FieldName = "MEASUREMENT";
filter.Conditions.Add(new ComparisonCondition(ComparisonOperator.Equals, "SYSBP"));
// Add the RecordFilter to field layout's RecordFilters collection.
fieldLayout.RecordFilters.Add(filter);
The last line throws an error saying FieldLayout does not contain a definition for RecordFilters.
Any ideas?
Cheers as always,
Kevin
Just figured out I am using the express version of the grid so therefore I cant apply Record Filters.
I cant afford the full version at the moment so any ideas of how I can achieve this would be great.
Cheers,
PS. I also tried to get some ideas from the feature browser but the EditorStyle could not allow a Combobox.
I am not sure if I am getting any closer but here goes:
I have the following CellValuePresenter code:
<Style TargetType="{x:Type igDP:CellValuePresenter}" x:Key="Fkt">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
<ComboBox ItemsSource="{Binding Path=scncodes}" IsSynchronizedWithCurrentItem="True" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have placed this in the field settings:
<igDP:Field IsScrollTipField="True" Name="SCNCODE">
<igDP:Field.Settings>
<igDP:FieldSettings CellMinWidth="200" CellWidth="200" CellValuePresenterStyle="{StaticResource Fkt}" />
</igDP:Field.Settings>
</igDP:Field>
And scncodes is populated in code behind:
var scncodes = (from scncode in dsMapping.DATAMAPPINGs
select scncode.MEASUREMENT).Distinct();
I get the combobox on the grid but its empty.
I created a combobox on another part of the page and set the item source to the scncodes to check the query and that worked fine.
I then created a combobox in code but could not figure a way to reference it in XAML in the CellValuePresenter.
At this point I am stuck and not sure which way to go. If there are any sample out there I could get some idea from I would be very much obliged
It looks like that when setting the ItemsSource property of the ComboBox, you are setting it to a string, which is an array of chars and that is why each char is considered a different item. Is the SCNCODE field of type collection or string? If string, this is the expected behavior. If you want to display something else (data outside the datasource of the XamdataGrid), you have to make this field unbound, and bind the ItemsSource property of the ComboBox to a collection (and set DisplayMemberPath and ValuePath properties).
You can see some example of how to bind data to a XamComboEditor in the FeatureBrowser, which is similar to what you want to do with the ComboBox. The examples are under XamDataGrid - Control Composition - XamComboEditor in DataRecord Cell.
I got the selection from the treeview working as you suggested...many thanks :-)
As for the combobox, I have placed a (standard) combobox in a Datagrid with the intention to allow the user to either edit the value or when creating a new record select a value. Therefore for each existing row the cell should show the current value but when clicked show a list form a different source.
The style code looks like this
<Page.Resources>
<ComboBox ItemsSource="{TemplateBinding Content}" IsSynchronizedWithCurrentItem="True" />
</Page.Resources>
The implementation look like this
My first problem the cell only shows the first character then when you click on it the rest of the characters drop down on each row.
My next problem is how do I bind a different dataset to the combobox so the user can select from the list
Sorry if this seems like a newbie question.
Well, for filtering, you can use something like this in the SelectedItemChanged event handler for the tree view:
IQueryable<Product> products = null;
TreeViewItem newItem = e.NewValue as TreeViewItem;
//get the value of the "Filter"
object value = newItem.Header.ToString();
// check for the parent
bool hasParent = newItem.Parent != null ? true : false;
if (hasParent)
// get the property/field to createa the filter for
string property = (newItem.Parent as TreeViewItem).Header.ToString();
switch (property)
case "SupplierID":
products = from product in context.Products
where product.SupplierID.ToString() == value.ToString()
select product;
break;
case "CategoryID":
where product.CategoryID.ToString() == value.ToString()
// rebind
xamDataGrid1.DataSource = products;
Regarding RecordFiltering, this feature is not included in the Express version - only in full and trial - this is why you are getting this exception.
@ ComboBoxes, as the Express versions does not have the XamComboEditor control, you have to retemplate the CellValuePresenter and put a ComboBox inside its template. Then you can assign this style at the CellValuePresenterStyle property of the FieldSettings of a specific field.
Hope this helps.