Binding inside a Groupbox.Header?

Nov 16, 2010 at 12:19 PM

I've recently started using Caliburn.Micro, which I'm liking a lot - it's the first MVVM framework I've found that really makes sense to me. Great job!

However, I've bumped into a problem which I'm not sure how to solve: I'm using a WPF CheckBox to toggle the visibility of a Grid; this works perfectly from all-XAML code, but unfortunately CM doesn't apply a ViewModel property binding to the CheckBox. The problem seems to be that the CheckBox is inside a Groupbox.Header - if I move it out of that, the binding is applied correctly, with no other changes.

Obviously getting a property binding isn't necessary just to toggle visibility of the Grid, but I also want to clear out another couple of VM properties when the visibility is set to false (the CheckBox being "Change password?" and the Grid containing password input fields).

Thanks in advance :)

Coordinator
Nov 16, 2010 at 2:05 PM

I'm assuming this is a Silverlight application. In which case, the ViewModelBinder, when it traverses the element tree cannot find the Checkbox inside the Header. Have a read through of this discussion for a bit more context and possible options: http://caliburnmicro.codeplex.com/Thread/View.aspx?ThreadId=220381

Nov 16, 2010 at 2:30 PM
EisenbergEffect wrote:

I'm assuming this is a Silverlight application.

It's a WPF application, sorry for not making that clearer - I do mention "WPF CheckBox" in my post, but it's easy to miss I guess :)

I've looked around a bit in the VS debugger, and I can see that the GroupBox.Header isn't part of the VisualTree: it's a public property of the GroupBox control, inherited from HeaderedContentControl. My understanding of how conventions work is a bit sketchy, but my guess is that the default conventions don't check for & drill into HeaderContentControl?

Perhaps I should just try and dig into the CM source, but convention handling stuff is a bit daunting :)

Thanks for your reply, I'll try poking around.

Coordinator
Nov 16, 2010 at 3:06 PM

That's correct. Have a read through of that forum discussion, it will give you some more info. Basically, you will need to customize the ExtensionMethods.GetNamedElementsInScope method.

Nov 16, 2010 at 6:02 PM
Edited Nov 16, 2010 at 6:03 PM

Thanks for the hint, Rob - I checked out the latest CM (rev ee5bdeb605be), and added the following lines near the end of GetNamedElementsInScope (at line 159, after the else-case for childCount>0):

 

var headerControl = current as HeaderedContentControl;
if( (headerControl != null) && (headerControl.Header is DependencyObject))
{
	queue.Enqueue(headerControl.Header as DependencyObject);
}

 

And it seems to do the trick - I wonder if it's the appropriate way to handle the situation, though, and whether there's some extension point that could be used instead? I don't know if you'd want to include this patch in the baseline, and I'd hate having to re-add the patch for new releases :)

Coordinator
Nov 16, 2010 at 6:04 PM

I could add this to the WPF version. I'll create a ticket for it.