ChildWindow with MVVM

Feb 20, 2011 at 7:34 PM

Brian,

Have you used the ChildWindow in a MVVM situation? If yes, how did you impliment it?

I have been stuggeling the whole day now, but I can't get it to show. I think it has got todo with the fact that the window is not placed on a specific view so it isn't drawn.

My childwindow is a seperate user control which gets called by the ViewModel. This results in the _parenContainer being null which results in the control not being rendered on screen.

Before I investigate a solution, I first want to find out if you have done it already and how?

Thanks,

Marais

Feb 20, 2011 at 7:52 PM

I would recommend creating a property in your VM that would simply bind to the WindowState property of the ChildWindow.  When you want to show/hide the ChildWindow you would just modify the value of the property in your VM.  Keep in mind that the ChildWindow control must be part of the visual tree.

Mar 23, 2011 at 8:31 PM

I am also trying to implement the ChildWindow with MVVM.  I have WindowState bound to an INotifyPropertyChanged property on my ViewModel, but there are two issues:

1) The ChildWindow is visible when the application starts up, even though in the contstructor of my ViewModel I set the WindowState to Closed.  I have to manually click the X in the corner to get the ChildWindow to hide and begin to use the application.

2) I have a button wired to a command on my ViewModel that is supposed to show the ChildWindow, but after changing the WindowState prooperty to Open nothing happens. 

What gives?

Mar 23, 2011 at 9:35 PM

I see what you mean.  For some reason, the PropertyChanged in the ViewModel is null the second time you try to set the WindowState.  Your first issue can be solved by declaring your property like this:

   private Microsoft.Windows.Controls.WindowState _windowState = Microsoft.Windows.Controls.WindowState.Closed;
        public Microsoft.Windows.Controls.WindowState WindowState
        {
            get { return _windowState; }
            set
            {
                _windowState = value;
                OnPropertyChanged("WindowState");
            }
        }

I don't know what would cause the PropertyChanged event handler to be null.  I will look into this and see if I can find anything.

Mar 23, 2011 at 9:37 PM

Ah, just found it.  Make sure your binding is TwoWay.  I will make this the default binding.

WindowState="{Binding WindowState, Mode=TwoWay}"
Mar 23, 2011 at 9:39 PM
Edited Mar 23, 2011 at 9:47 PM

I think I found a way around it (literally at the same time I got your email – funny how that works) – I changed the WindowState binding to TwoWay.

 

 

Mar 23, 2011 at 9:40 PM
Edited Mar 23, 2011 at 9:46 PM

Ha! I just got your answer after sending you my answer.

Well, I guess by the mouth of two or more witnesses right? J 

 

Thanks for the follow-up! You’ve got an awesome set of controls!

Mar 23, 2011 at 9:43 PM

Fixed!  The fix is avilable in the latest source code download.

Mar 23, 2011 at 9:44 PM
Edited Mar 23, 2011 at 9:46 PM

Oh – I realized a made a change to your source as I’ve been playing with it. It seems the default behavior is for the ChildWindow to start open. Line 245 of ChildWindow has the default value being WindowState.Open. When I switched that to WindowState.Closed then my MVVM’ed app worked much better (the ChildWindow only showing up when I told it to).

Mar 23, 2011 at 9:45 PM
Edited Mar 23, 2011 at 10:35 PM

Wowsers! That’s got to be some sort of a record!

(out of curiosity, what’s it take to get that pushed to NuGet? I’m not familiar with the NuGet publishing procedure – that’s why I ask. Well, that and I’d prefer to leave my NuGet reference in my code instead of manually referencing an assembly I built by hand)

Mar 23, 2011 at 9:49 PM

Well to clarify, the fix is only available in the source code.  Publishing to NuGet is actually pretty simple.  Here is a link that may assist you: http://www.hanselman.com/blog/CreatingANuGetPackageIn7EasyStepsPlusUsingNuGetToIntegrateASPNETMVC3IntoExistingWebFormsApplications.aspx

I am hard at work on v1.4.0.  As soon as it is at a stable state then I will be publishing v1.4.0 to NuGet.

Mar 23, 2011 at 10:37 PM

Will v1.4 also include the change to have the default state of ChildWindow be closed?

Mar 23, 2011 at 11:04 PM

Why do you believe that is should be Closed by default?

Mar 23, 2011 at 11:08 PM

Well, from an imparative viewpoint it doesn't matter - I'd just explicitly set the WindowState to closed and I'm done with it.

From an MVVM standpoint my ChildWindow could be bound (as it is in my case) to a ViewModel that is not yet instantiated and therefore the ChildWindow shows up at the beginning of my application covering up everything and without any data or purpose.  When my main ViewModel decides it's time to show the ChildWindow then it creates the ChildWindowViewModel with all the data that the ChildWindow needs, and that ChildWindowViewModel sets the WindowState to Open.  _That_ is the appropriate time (in my opinion) for the ChildWindow to appear. 

It seems to me the ChildWindow shouldn't be seen until it's asked to show itself, that's all.

Your thoughts?  What's the reasoning behind it defaulting to 'Open' instead of 'Closed'?

Mar 23, 2011 at 11:20 PM

I have no real reasoning behind defaulting it to Open.  It is just the value that it got set at :0).  I have never had any feedback on what users actually preferred until now.  You make valid points and I will default it to closed.  Thanks for the feedback.

Mar 23, 2011 at 11:22 PM

Thanks for providing a functional feedback loop! :)  I eagerly await 1.4

Apr 5, 2011 at 12:52 PM
Edited Apr 5, 2011 at 12:55 PM

Defaulting the WindowState to "closed" would mean that the childwindow will not be visible in the Designer if there is a binding in place for WindowState ? If that's correct, that would be another point in favor of it. I prefer to have my main window fully visible by default. But I wonder if there would be an easy way to switch the visibility of the child window in designer mode from visible to invisible and vice-versa (a DesignWindowState property like the size properties for a user control ?) :

<extToolkit:ChildWindow Caption="Test" Width="300" IsModal="True"  
DesignWindowState="Closed" WindowState="{Binding Path=IsTestAdded, Converter={StaticResource boolToWindowState}}">

Otherwise, actually it hides the main window by default, unless there is another way to organize the user controls to design them besides embbeding the childwindow code in the mainwindow xaml ?

Apr 5, 2011 at 2:33 PM

Added a check for ChildWindow.  If it is in design mode it will show in the designer.  At runtime the ChildWindow will be hidden by default.

Apr 5, 2011 at 2:57 PM

This still leaves the issue of the developer not able to hide it in design view. My childwindows are closed except for when I actually work on it. Most of the time, I am working on the actual windows which owns it, so it needs to be closed [the child window].

Have a property to change the state in the designer is a better solution. Would it be possible to impliment an option like Microsoft implimented for the Height of the window? This would result in a something like this: d:DesignerWindowState="Closed".

It would be great if that would be possible.

Apr 5, 2011 at 3:00 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.