Friday, January 30, 2009

Two-way Data Binding with WPF DataGrids

We’re making use of the the WPF Toolkit’s DataGrid control in my current project and have solved a few things along the way that weren’t entirely obvious to us at the start. One of these things was figuring out how to automatically reflect domain object changes in the UI.

Of the three developers on this project, Nik Clarkson has the most background with WPF and we usually throw out ideas to him and he “translates” what we want to do to into WPF terms and we’re off and running. In the case of getting our UI to reflect domain model changes, he mentioned BindingMode.

I was able to find some examples that showed how to do this in XAML pretty quickly, but I spent a few cycles trying to get this to work with a DataGridColumn that I was adding programmatically. My first attempt looked like how you’d do it in XAML a-la new Binding("Price, Mode = BindingMode.Two-way”), but that didn’t work.

I decided to make up a fresh batch of coffee in the team french-press, and then it hit me: object initializers. A quick edit and I ended up with following:

var priceColumn = new DataGridTextColumn{ Header = "Price", Width = DataGridLength.Auto,
Binding = new Binding("Price") { Mode = BindingMode.Two-way, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }};
This worked perfectly with the “Price” property I was binding to, since this was a property on one of our LINQ to SQL objects, and as such was raising the property-changed event for us in the generated code. When I went to do the same thing with another column (one not generated by the LINQ to SQL designer), I wasn’t seeing my edits reflected in my UI, but did see them in the domain objects via the debugger.

I had forgotten to raise the property-changed event in my ProposedPrice setter, so once I changed it to the following, everything worked great.
if (_proposedPrice != value)
_proposedPrice = value;

Wednesday, January 28, 2009

I just discovered something

One Kashi honey/cinnamon oatmeal packet plus a scoop of chocolate Muscle Milk with a bit of water and milk makes for one tasty breakfast/snack.

That is all.

Monday, January 26, 2009

Pasta Primavera

Here’s one of my old standby recipes that’s extremely easy to make and is quite tasty.

1lb cooked linguini 2 cups broccoli
2 tbsp olive oil 12oz fresh mushrooms
1 small zucchini cut in small sticks several cloves garlic – diced
1 small white onion 2 carrots cut into small sticks
1 small red bell pepper 12oz can evaporated skim milk
2 vegetable bullion cubes 1 1/4 tsp corn starch
2 plum tomatoes 2 tbsp parmesan cheese
Italian herbs (basil, oregano, etc)

In large skillet over medium heat, warm olive oil and then add mushrooms, onion, garlic and carrots. Stir frequently until almost tender then add red pepper and cook. In a separate pan, steam the broccoli for several minutes until tender and then set aside.

In blender, mix evaporated milk, vegetable bullion, corn starch and herbs (and a 1/2 tsp of salt if desired). Pour mixture over vegetables cooking in skillet and bring to boil. Cook for one minute, stirring nearly constantly.

After draining the pasta, return to a large pot (4 qt or so), dump the skillet contents over the pasta, and top with the tomato, broccoli and parmesan and stir.

Friday, January 16, 2009

AutoScroll panels in WPF

I’m still pretty new to WPF, coming from a WinForms background, and I keep running into situations where stuff that I can do easily in WinForms just isn’t there in WPF. Well, it’s there, I just don’t know how to do it. My latest example was a requirement to add some auto-scrolling to a WrapPanel, and I couldn’t find any sort of “overflow=auto” type setting on the WrapPanel, so off to Google I went.

Turns out WPF provides a pretty simple mechanism for allowing scroll: ScrollViewer. This control allowed me to do exactly what I needed to get done, but it needed to be treated as a container around my WrapPanel - a concept I’m seeing more and more as I get into WPF – another example of this was adding borders to a panel.

Here’s an example of a WrapPanel that has vertical auto-scrolling:

<ScrollViewer Name="MyScroller" VerticalScrollBarVisibility="Auto">
<WrapPanel Name="MyPanel"></WrapPanel>

LINQ to SQL Entity Association Quirks

On my current project, we’re trying to adhere to the Simplest Thing That Could Possibly Work principle and this unfortunately led to some pains with LINQ to SQL surfacing after we had claimed victory on a few stories.

We are early in this project, and didn’t have a wire-frame of what the screen flow would eventually look like, so we were just adding buttons to allow a user to see each piece of functionality as we delivered stories. But, as we finished each story, it became more and more clear that we needed to do some proper UI soon.

Enter “The Wizard”
We realized that the independent stories were really leading up to a flow of execution that a wizard style approach seemed to be a perfect fit for. Things came together pretty well, until I started to mess around with back-and-forward navigation and I started to get “An attempt was made to remove a relationship between a PARENT and a CHILD. However, one of the relationship’s foreign keys (CHILD.PARENT_ID) cannot be set to null”. This only occurred when I did any back-and-forward navigation and if I only navigated the happy-path straight through the wizard, things worked just fine.

Part of my problem was that I wasn’t submitting my changes until the user completed work in the wizard, but I was running code to disassociate existing entities (that may or may not have been persisted to the database) from local collections – each time the user left particular steps in the wizard. I was able to overcome some of those quirks with the “what didn’t work” approach below, but I still would saw the “null relationship” error on a fairly regular basis.

After much time searching Google, and trying a number of approaches as recommended here and here, I started to realize that I wasn’t properly disassociating my entities from their parent relationships before I deleted them.

What didn’t work:

catch(InvalidOperationException ) {}

What did work:

childEntity.Parent = null;
catch(InvalidOperationException ) {}