ehahn9

I'd like to build a UserControl which modifies some data object. Normally, you'de just do:

<l:MyControl DataContext="{Binding MyData}" />

And the control could bind to invidivual properties of MyDatato the UI, etc. Easy stuff.

But what if the control wants to behave more like a dialog, with OK and CANCEL buttons. You can't bind to the data directly because you don't want to edit it live (in case the user cancels). You could bind to a copy inside the control (assuming the data is ICloneable for now):

Code Block

DataContextChanged += new DependencyPropertyChangedEventHandler(MyControl_DataContextChanged);

...

void MyControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)

{

Copy = ((ICloneable)DataContext).Clone();

}

...

<TextBox Text="{Binding Path=Copy.Name}" />

But here's where I'm stuck. When the user clicks OK, I'd like the control to replace the data with the new, edited data.

The {Binding Path=MyData} (above) passes the instance of the MyData object, not a reference to it. So the OK button handler cannot possibly change the container to have a new instance, it can only modify properties in the existing instance. Modifying the instance might be bad anyway, because one might end up with missing/orphaned event wiring, etc. (In my app, everything is fully INotifyPropertyChanged and the parents do indeed unwire and rewire changes, so I could go this route if I passing a C# ref were easy).

The only alternative I can think of would be to use reflection to walk the properties of the control's edit result and copy them back to the original! That seems totally hacky.

Or maybe I have to implement IEditable, something like:

Code Block

interface IEditable : ICloneable

{

void Apply(object edit);

}

So the OK button logic does:

Code Block

private void OKButton_Click(object sender, RoutedEventArgs e)

{

((IEditable)DataContext).Apply(Copy);

}

But this approach means a pretty big burden on each editable object.

I'd be delighted if someone had some great design ideas here. I suppose this same issue exists in WinForms - how do you implement OK/Cancel behaviors which are OO-friendly My app has a number of these sorts of controls and I'm going nuts with each one! What am I missing Thanks a zillion.



Re: Windows Presentation Foundation (WPF) Users controls with "OK/Cancel" semantics design/advice?

Yi-Lun Luo - MSFT

Hello, so you want to delay updating data source. By default, on a two way data binding, UpdateSourceTrigger is set to LostFocus. That means each time an input Control such as a TextBox loses focus, the data source is updated. To avoid this, you can set UpdateSourceTrigger of individual Controls (not DataContext) to Explicit, and manually update them when you click OK Button. Please refer to http://msdn2.microsoft.com/en-us/library/system.windows.data.binding.updatesourcetrigger.aspx.






Re: Windows Presentation Foundation (WPF) Users controls with "OK/Cancel" semantics design/advice?

ehahn9

Excellent idea - thanks so much. I had forgotten that I could control the binding update ... DOH!

The only challenge I can see with this approach will be ensuring that bindings all the way "down" the visual tree are respected as Explicit. For example, when the dialog in question uses some other user controls which it binds to objects in the target - like this

<UserControl x:Class="MyControl" ...
<l:CalendarControl Calendar="{Binding Path=Calendar, UpdateSourceTrigger="Explicit"/}"/>

In this case, I wonder what happens if the CalendarControl does NOT have an explicit UpdateSourceTrigger for its bindings to pieces of the calendar (day/month/year, for example)... Hard to see how WPF would know how to implement this, unless the UpdateSourceTrigger is inherited by subordinate bindings to the same DataContext or DP...