views:

759

answers:

5

Hello!

I have two UserControls ("UserControlParentView" and "UserControlChildView") with MVVM pattern implemented in both controls. Parent control is a container for Child control and child control's property should be updated by data binding from Parent control in order to show/hide some check box inside Child control.

Parent Control Description

UserControlParentViewModel has property:

    private bool isShowCheckbox = false;
    public bool IsShowCheckbox
    {
        get { return isShowCheckbox; }
        set { isShowCheckbox = value; NotifyPropertyChanged("IsShowCheckbox");  }
    }

UserControlParentViewModel - how I set DataContext of Parent control:

    public UserControlParentView()
    {
        InitializeComponent();

        this.DataContext = new UserControlParentViewModel();
    }        

UserControlParentView contains toggle button (in XAML), bound to UserControlParentViewModel's property IsShowCheckbox

<ToggleButton Grid.Column="1" IsChecked="{Binding IsShowCheckbox, Mode=TwoWay}"></ToggleButton>

Also Parent control contains instance of child element (somewhere in XAML)

<local:UserControlChildView IsCheckBoxVisible="{Binding IsShowCheckbox}" ></local:UserControlChildView>

so property in child control should be updated when user togggle/untoggle button. Child control contains Boolean property to be updated from parent control, but nothing happened! Breakpoint never fired!

Property in UserControlChildView that should be updated from Parent control (here I plan to make chechBox visible/hidden in code behind):

    public bool IsCheckBoxVisible
    {
        get { return (bool)GetValue(IsCheckBoxVisibleProperty); }
        set { SetValue(IsCheckBoxVisibleProperty, value); }
    }
    // Using a DependencyProperty as the backing store for IsCheckBoxVisible.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsCheckBoxVisibleProperty =
        DependencyProperty.Register("IsCheckBoxVisible", typeof(bool), typeof(TopMenuButton), new PropertyMetadata(false));

So the question is - what I'm doing wrong? Why child's property is never updated? BTW - there is no any binding error warnings in Output window...

A: 

I can't see all your code, so I can't work out everything, but a couple of questions:

In your DependencyProperty.Register call, you specify typeof(TopMenuButton), which should be the UserControlChildView - I don't know if that is your view or not?

You don't set up a callback method for property changed. To do this you would have to define the properties for the FrameworkPropertyMetadata, before registering the depencencyProperty like so:

FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.PropertyChangedCallback += OnSpacePropertyChanged;

You'd then have to declare OnSpacePropertyChanged, but you can at least respond to setting the property from there.

Dave Arkell
My mistake - for simplicity I decided to rename TopMenuButton to Child control but forgot to rename it in depend.prop.declaration - sorry!
MagicMax
A: 

I am pretty sure you can't bind to a dependency property on a user control in Silverlight 3. I've tried it myself 9 months ago, and attempted all sorts of things to get it to work. Eventually I read somewhere that it simply wasn't possible. I have done it in WPF, so was beating my head on it for a while, thinking it was my implementation.

So, on the surface your code looks correct but this won't help.

I thought it was slated as something to be fixed in SL4.

Are you using SL4?

ross
Yes, I'm using SL4..
MagicMax
A: 

Hoho!! I've got it to work!

In child control I've changed property a bit

    public bool IsCheckBoxVisible
    {
        get { return (bool)GetValue(IsCheckBoxVisibleProperty); }
        set { SetValue(IsCheckBoxVisibleProperty, value); }
    }
    // Using a DependencyProperty as the backing store for IsCheckBoxVisible.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsCheckBoxVisibleProperty =
        DependencyProperty.Register("IsCheckBoxVisible", typeof(bool), typeof(UserControlChildView), new PropertyMetadata(false, new PropertyChangedCallback((d, dc) => 
        {
            var button = d as UserControlChildView;
            button.CheckBoxVisibility = ((bool)dc.NewValue) ? Visibility.Visible : Visibility.Collapsed;
        })));

so now I have new event subscription (see anonymous method) and it fires when in parent control IsShowCheckbox property is changed!

CheckBoxVisibility depend.property looks like this:

    public Visibility CheckBoxVisibility
    {
        get { return (Visibility)GetValue(CheckBoxVisibilityProperty); }
        set { SetValue(CheckBoxVisibilityProperty, value); }
    }

    // Using a DependencyProperty as the backing store for IsCheckBoxVisible.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CheckBoxVisibilityProperty =
        DependencyProperty.Register("CheckBoxVisibility", typeof(Visibility), typeof(UserControlChildView), new PropertyMetadata(Visibility.Collapsed));

Constructor of serControlChildView looks like:

    public UserControlChildView()
    {
        InitializeComponent();

        this.LayoutRoot.DataContext = this;
    }

So seems like it works! Thank you for your help, folks!

MagicMax
+1  A: 

You don't state where you put the breakpoint "never fired!". My guess is you placing a break point in the set mutator method of the IsCheckBoxVisible property.

You are operating under the assumption that the binding on that property will at some point cause the set method to be called when assigning the value. However the Silverlight binding framework actuall calls SetValue directly. It passes to the SetValue method the value of IsCheckBoxVisibleProperty and the value to be assigned.

AnthonyWJones
You right! Thanks for info!
MagicMax
A: 

Ok, it seems like everything worked fine and I was confused just by non-fired breakpoint.

For simplicity I've decided to remove IsCheckBoxVisible boolean depend.property from the Child control and to bind checkBox visibility in Child control directly to CheckBoxVisibility depend.property (type is Visibility).

Also in the Parent control now I have this:

<local:UserControlChildView CheckBoxVisibility="{Binding Path=CheckboxControlVisibility}"></local:UserControlChildView>

So in the Parent control now I have CheckboxControlVisibility property (type is Visibility)

MagicMax