views:

497

answers:

2

I've created a table in Microsoft Sql CE that I'm using to hold some data. I've generated an ORM via SqlMetal and I've pulled the datasource into my WPF project.

I want to create a simple WPF form that can be used to edit a record in the table via the ORM-generated classes. I want this form to support typical OK/Cancel semantics. I've created the form in what I believe to be the typical fashion, using TwoWay databinding on the respective fields to bind against an instance of the object from the ORM. For example, given an object in the ORM that has a property "TaskName", I've included the following in my WPF form:

<Label Grid.Column="0" Grid.Row="0" >
    Name:
</Label>
<TextBox Name="txtName" Grid.Column="1" Grid.Row="0" 
         Text="{Binding TaskName, Mode=TwoWay}" AcceptsReturn="False"
         MaxLines="1" />

This, combined with a DataContext assignment in code:

var newRow = new OrmGeneratedClass();
// Populate default values on newRow, e.g.    
detailWindow.DataContext = newRow;
detailWindow.ShowDialog();

can work reasonably well for creation of a new row. All changes made via the form are immediately reflected in the underlying OrmGeneratedClass. The problem is that there's no immediate support for canceling changes if, e.g., the OrmGeneratedClass is filled with previously saved values.

What is a good design for this scenario, or am I designing it wrong before I get to this point? I'm a newbie with WPF and the Sql Server datasource/ORM integration aspects. (This is a personal project that I'm using to learn both technologies.)

I have a couple of thoughts and will place them in the answers

+1  A: 

One possible solution would be to look for a cancel result from the dialog and, using the ORM object's primary key, retrieve the data from the database every time the user cancels to verify that the object contains the value it had in the database. This assumes that the value's most recently confirmed value has already been stored in the database. (Probably a fair assumption in a program as simple as this will be.)

It might look something like this (non-compiled) code:

var existingRow = GetExistingRow(someConditionOrWhatever);
detailWindow.DataContext = existingRow;
if(!detailWindow.ShowDialog())
{
    existingRow = GetExistingRow(someConditionOrWhatever);
}

I don't know if I like round-tripping to the database like that, though.

Greg D
http://groups.google.com.au/group/wpf-disciples/web/wpf-and-xaml-coding-guidelines includes some useful guidelines, including a better technique for the DataContext assignment that I'm performing in the question.
Greg D
+6  A: 

Paul Stovell has a brilliant article about creating an adapter for the IEditableObject interface that allows you to databind and allow apply/revert behaviour.

http://www.paulstovell.com/blog/runtime-ui-binding-behavior-ieditableobject-adapter

The adapter wraps around your ORM object and automatically caches changes so you can either apply the changes or revert back to the original.

Cameron MacFarland
Brilliant! This looks like it addresses exactly what I'm looking for. Thanks!
Greg D
Yeah I found the article a while ago, and have used it in several projects. Saved me heaps of time.
Cameron MacFarland