Question

I have built a user control (ctlToolbarEdit) that has some buttons on it - but for simplicity sake let's say there is one button: cmdSave.

I want ctlToolbarEdit to expose a IsSaveEnabled property that when set to true sets cmdSave.IsEnabled = true, and (obviously) when false sets cmdSave.IsEnabled = false.

Finally, I want to be able to bind to that property .. I want to bind IsSaveEnabled to the IsValid property of the View Model the form hosting the control is bound to

So. Here is the code behind for ctlToolbarEdit

    private readonly DependencyProperty IsSaveEnabledProperty = DependencyProperty.Register("IsSaveEnabled", typeof(bool), typeof(ctlToolbarEdit));

    public ctlToolbarEdit()
    {
        InitializeComponent();
    }

    public bool IsSaveEnabled
    {
        get { return (bool)GetValue(IsSaveEnabledProperty); }
        set 
        {   
            SetValue(IsSaveEnabledProperty, value);
            cmdSave.IsEnabled = value;
        }
    }

and here is the XAML of the form that is hosting this user control:

<ctl:ctlToolbarEdit IsSaveEnabled="{Binding IsValid}" />

As a test, I also added this line of XAML to the form hosting ctlToolbarEdit (so it is replicating the behaviour I am trying to produce):

<Button Name="cmdSaveTest" Content="Save" IsEnabled="{Binding IsValid}" />

My results are this:

  • The Button I added works as expected. Whenever the IsValid property changes then the IsEnabled value of the cmdSaveTest button changes (I can see it enabling/disabling). This tells me that the IsValid property is firing properly ... in other words I CAN bind to that property, so I am happy that the binding to that property and the view model are all okay.

  • The cmdSave button within ctlToolbarEdit does nothing.

In fact: I put some breakpoints on the getter and setter of the property in ctlToolbarEdit and these never seem to fire.

Could anyone please tell me what painfully obvious thing I have overlooked?

EDIT

Typical. You spend hours searching, finally bite the bullet and post on Stack Overflow, and almost immediately find something that goes to answer your question.

I now know:

  • My property getter and setter are ignored by the CLR; it invokes GetValue and SetValue directly. This is why my breakpoints are not being honoured (that code is not actually firing!) and why the IsEnabled property of cmdSave is not working.

So: that all said ... how do I actually achieve what I want to achieve, then? Help gratefully appreciated.

EDIT

Ok ... so more progress; I see you use the PropertyMetadata. I added:

, new PropertyMetadata(new PropertyChangedCallback(OnIsSaveEnabledChanged))

to the IsSaveEnabledProperty DependencyProperty statement (making it:

private readonly DependencyProperty IsSaveEnabledProperty = DependencyProperty.Register("IsSaveEnabled", typeof(bool), typeof(ctlToolbarEdit), new PropertyMetadata(new PropertyChangedCallback(OnIsSaveEnabledChanged)));

But now the OnIsSaveEnabledChanged method I need to write has to be 'static', and I cannot get to cmdSave within that method.

Now I really am stuck. Any help?

DS

Was it helpful?

Solution

With a typical MVVM pattern, you would do this the other way around: Your command's CanExecute/IsEnabled property would control the IsEnabled property on your control. So, When your viewmodel decides that saving is unavailable, it would cause your command's CanExecute/IsEnabled flag to be false, and any controls that use that command would disable themselves. For an example, have a look at how a Button control works with an ICommand.

http://msdn.microsoft.com/en-us/library/ms752308.aspx

http://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx#sec10

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top