Custom UserControl "IsEnabled" data binding not working
Asked Answered
M

3

6

I have a kinda awful problem with my WPF application right now...

I have a custom UserControl used to edit details of a component. It should start by being not enabled, and become enabled as soon as the user chose a component to edit.

The problem is: the IsEnabled property does not even change.

Here is my code:

<my:UcComponentEditor Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  
                        IsEnabled="{Binding EditorEnabled}"
                              DataContext="{Binding VmComponent}" />

EditorEnabled is a property in my ViewModel (VmComponent), and is by default false, becomes true when the user chose a component or created one

Just for the record, in my ViewModel:

private Boolean _editorEnabled = false;

    public Boolean EditorEnabled
    {
        get { return _editorEnabled; }
        set 
        {
            _editorEnabled = value;
            OnPropertyChanged("EditorEnabled");
        }
    }

When I try to launch my app, the UserControl is starting... enabled. I added breakpoints everywhere, the EditorEnabled is false from the beginning.

I also did a horribly stupid thing to try to figure out what's happening: I created a converter (so useful -- converting a boolean to boolean -- eh), put a breakpoint on it, and... The code is never reached.

<my:UcComponentEditor Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  
                        IsEnabled="{Binding EditorEnabled, Converter={StaticResource BoolConverter}}"
                              DataContext="{Binding VmComponent}" />

That probably means that the property isEnabled is never set, since the converter is never reached.

Do you see any kind of problem there? I started working in WPF about one week ago and therefore I may have missed something essential...

Thank you very much for your time :-)

Magazine answered 17/3, 2011 at 11:50 Comment(3)
does breakpoint stop at _editorEnabled = value;?Pyszka
Is VmComponent being properly created? As far as I'm aware, that binding won't initialise a new object.Guadalajara
@Fun Mun Pieng: Yes, it goes through the setter @Harry: Yes, VmComponent is created, and properly working for all other needs, only this one is not workingMagazine
H
3

You should add a DependencyProperty for the binding to work properly. See here for more information.

Code-behind:

public static readonly DependencyProperty EditorEnabledDependencyProperty = DependencyProperty.Register("EditorEnabled", typeof(bool), typeof(UcComponentEditor), new PropertyMetadata(false));

public bool EditorEnabled
{
    get { return (bool)base.GetValue(UcComponentEditor.EditorEnabledDependencyProperty); }
    set { base.SetValue(UcComponentEditor.EditorEnabledDependencyProperty, value); }
}
Hoarhound answered 17/3, 2011 at 12:7 Comment(7)
Is it really worth to be added? I mean, the control already naturally has an IsEnabled property. I thought that adding a DependencyProperty having the same role than IsEnabled would lead to bad-coding :-/Magazine
Yes - Dependency Properties are heavily used in XAML - please see the link I posted for more information. I updated my answer with an example.Hoarhound
No it is not necessary to add a DependencyProperty - the code looks as it should work as it is. I would try to set the datacontext explicit - or make a propertychanged on the VmComponent property - or set the property value before InitializeComponent.Karakoram
@Josh: Don't bother giving me an example, I already worked with DependencyProperties, I'll try to implement one :) @Rune: PropertyChanged is already on, doesn't change anything. I tried setting the Enabled value in the ViewModel constructor (I'm working with mvvm there so I'm willing not to put anything in the xaml.cs code-behind file)Magazine
@Josh M. :Hey again, it actually works with a DependencyProperty setting the IsEnabled property. However I find it very unclear to need to add such property just to handle something already existing. Thanks anyway, your help was useful, I'll let this topic open to see if somebody else has a logical explanation :)Magazine
Dependency Properties handle two-way communication between a binding source and a binding destination. They are responsible for notifying your control that the value has changed. If you "bind" your control directly to a property, the control has no way of knowing when/if the property has changed. The only way it could is if it continually polled the value of the property to see if it has changed. Dependency Properties fix this issue and it is the proper way to implement what you have posted. You should perhaps read a bit more about Dependency Properties but I'm glad it helped.Hoarhound
Okay, I'll keep that in mind from now on, I might have to look further into Dependenvy properties then if you say so :) Thank you very much!Magazine
L
2

The issue I think is that there is a binding on the DataContext property of the user control. Which means the EditorEnabled property should be a property in the VmComponent object. At least that's what my problem was.

To get around it, I specified a proper source to the binding of IsEnabled. Once I did that the control started working as expected.

Hope that helps.

Lon answered 25/8, 2012 at 12:14 Comment(0)
O
2

Encapsulating your control in a DockPanel (for example) will remove the need for a DependencyProperty.

You can then simply do your binding with the dockpanel instead of the custom control. Setting the variable bound to IsEnabled on the Dockpanel will automatically enable or disable the items contained in the Dockpanel.

Orethaorferd answered 25/2, 2014 at 8:3 Comment(1)
Putting the UserControl in a Border solved the issue.Ytterbia

© 2022 - 2024 — McMap. All rights reserved.