9 Replies - 14024 Views - Last Post: 27 June 2012 - 12:04 PM Rate Topic: -----

#1 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Checkbox.IsChecked binding not working as expected

Posted 13 June 2012 - 11:50 AM

In my WPF UserControl I have several controls that have their state/value bound to dependency properties in the C# code behind. Some work, but the checkboxes don't. Does someone see what I'm doing wrong or is there a trick to checkboxes?

The area in question is highlighted in yellow:

Attached Image

WPF:
Here we see the checkbox and the IntegerUpDown control in a StackPanel. When the value of the IntegerUpDown changes the code behind property is updated and the PropertyChanged event is raised. My breakpoint in the method handler for the PropertyChanged event is hit and works as expected.

When the CheckBox is checked/unchecked however there is no event raised. And as near as I can tell both properties are handled in an identical manner.
Both are Two way, both are dependency properties, both are raising the PropertyChanged event.

             DataContext="{Binding RelativeSource={RelativeSource Self}}"
...

                <StackPanel MinWidth="{Binding Width, ElementName=tbxPrefix}" Margin="0 0 5 5">
                    <CheckBox Name="chkSequence"
                              Content="Sequence"
                              IsChecked="{Binding UseSequence,
                                                  Mode=TwoWay}"
                              IsThreeState="False" />
                    <extToolkit:IntegerUpDown x:Name="nudSequence"
                                              MinWidth="{Binding Path=MinWidth,
                                                                 ElementName=tbxPrefix}"
                                              IsEnabled="{Binding Path=IsChecked,
                                                                  ElementName=chkSequence}"
                                              Value="{Binding SequenceNumber,
                                                              Mode=TwoWay,
                                                              FallbackValue=1001}" />
                </StackPanel>


UPDATE: Well that formatted for shite. This should be easier to read
Attached Image




C# code behind

               public static DependencyProperty SequenceNumberProperty = DependencyProperty.Register("SequenceNumber",
                                                                                              typeof (int),
                                                                                              typeof (NamerUC),
                                                                                              new PropertyMetadata(1001));

        public int SequenceNumber
        {
            get { return (int) GetValue(SequenceNumberProperty); }
            set
            {
                SetValue(SequenceNumberProperty, value);
                RaisePropertyChanged("SequenceNumber");
            }
        }

                public static DependencyProperty UseResetSequenceProperty = DependencyProperty.Register("UseResetSequence",
                                                                                                typeof (bool),
                                                                                                typeof (NamerUC),
                                                                                                new PropertyMetadata(default(bool)));


        public bool UseSequence
        {
            get { return (bool) GetValue(UseSequenceProperty); }
            set
            {
                SetValue(UseSequenceProperty, value);
                RaisePropertyChanged("UseSequence");
            }
        }


As I said, when the int property changes I get a hit on the event handler which then updates an object that can be serialized.

Attached Image

As I am thinking the UseSequence property should be bound to the checkbox's .IsChecked property, so changing that should change the property should raise the event should activate this method. But it doesn't.

So anyone see/know what could be keeping it from happening?

This post has been edited by tlhIn`toq: 13 June 2012 - 11:53 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Checkbox.IsChecked binding not working as expected

#2 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Re: Checkbox.IsChecked binding not working as expected

Posted 13 June 2012 - 12:39 PM

Unless someone has something better, here's what I've learned:

The RadioButton has a known problem with this same type of binding on the .IsChecked property - and hasn't been fixed since .NET 3 or older(as posters are asking if it can be fixed in 3.5) Apparantly the RadioButton doesn't update the dependancy property like it should but updates the property directly.

I didn't find anything about this being documented on the CheckBox, but we all know the RadioButton and CheckBox are closely related and possibly inherit from a common object or at least share a lot of same code.

As a Band-Aide I am reacting to the .Checked and .Unchecked events to programmatically update the code-behind property; which then correctly raises the .PropertyChanged event.


I have all my CheckBoxes pointing to the same method handler to centralize updating. Within that I have used a switch construct to map the various checkboxes to their associated properties. Its a hack, but that's what you have to do when the control is fraked. WPF binding was supposed to keep us from having to go through all the pain of WinForm binding or manually handling these things to keep properties synchronized. I wish MS coders were held accountable for fixing their screwups just like the rest of us are.


                    <CheckBox Name="chkSequence"
                              Content="Sequence"
                              IsThreeState="False"
                              IsChecked="{Binding UseSequence,
                                                  Mode=OneTime}"
                              Checked="chkBox_CheckChanged"
                              Unchecked="chkBox_CheckChanged"
                              />



        private void chkBox_CheckChanged(object sender, RoutedEventArgs e)
        {
            if (sender.GetType() != typeof(CheckBox)) return;
            CheckBox temp = (CheckBox) sender;
            switch (temp.Name.ToString().ToLower())
            {
                case "chksequence":
                    UseSequence = temp.IsChecked == true;
                    break;
            }
            CalculateFileName();
        }


Like I said, its a patch. I'll probably make a proper working CheckBox based on this wrapper for a proper working RadioButton.
http://pstaev.blogsp...roperty-of.html
Was This Post Helpful? 0
  • +
  • -

#3 Robin19  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 271
  • View blog
  • Posts: 550
  • Joined: 07-July 10

Re: Checkbox.IsChecked binding not working as expected

Posted 14 June 2012 - 11:51 AM

CheckBox and RadioButton are both types of ToggleButton but with a different look. Everything under the hood is the same. .IsChecked is a nullable Boolean type. I wonder if it doesn't work because you are trying to bind it to a non-nullable Boolean type?

Source- WPF 4: Unleashed p265-267. Binding to objects isn't covered for another 100 pages. Sometimes a paper book with an index is quicker than the entire web.
Was This Post Helpful? 0
  • +
  • -

#4 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Re: Checkbox.IsChecked binding not working as expected

Posted 27 June 2012 - 09:27 AM

Apparently I'm really struggling with binding properties to controls in WPF. Sometimes they work and sometimes they don't and I can't for the live of me get a handle on it.

Simple checkbox on a Window:

XAML:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
... blah blah...

<CheckBox Name="chkRemoveEnding"
Margin="5,0,0,0"
VerticalAlignment="Center"
Checked="Step1_SettingsChanged"
Content="Remove ending "
IsChecked="{Binding UseRemoveEnding,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Unchecked="Step1_SettingsChanged" />



So to my understanding the IsChecked state should be bound to the dependancy property boolean "UseRemoveEnding"
C#
      public bool UseRemoveEnding
        {
            get { return (bool)GetValue(UseRemoveEndingProperty); }
            set
            {
                SetValue(UseRemoveEndingProperty, value);
                RaisePropertyChanged("UseRemoveEnding");
            }
        }


Yet when I run this the breakpoint on C# line 6 (the set method of the property) is never hit.
Later in code when I try to work with this property I see that it has never changed to true when the checkbox is ticked (my backup confirmation of this working).

I've tried this as both bool and bool?.
I've tried removing the .Checked and .Unchecked subscriptions from the XAML in case there was some type of interception taking place.

The event handler for .Checked and .Unchecked events works:
Attached Image

I know I am subscribed to PropertyChanged event. When the checkbox is checked it calls and event: Checked="Step1_SettingsChanged"
that causes a recalculation, that causes a different property to be changed and my PropertyChanged event handler does respond to that.

Adding to my confusion is I have the exact same concept employed on a UserControl and it works fine:
Attached Image

So does anyone see WTF I'm doing wrong for something that is (meant to be) so straight-forward?
I feel like a fraking rookie again trying to pick up WPF and the frustration of something this simple is almost enough to kick me back to WinForms despite the coolness of WPF.

This post has been edited by tlhIn`toq: 27 June 2012 - 09:28 AM

Was This Post Helpful? 0
  • +
  • -

#5 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Re: Checkbox.IsChecked binding not working as expected

Posted 27 June 2012 - 09:45 AM

UPDATE: Part of confusion found.
The reason it works in the other UserControl for hte UsePrefix property is because binding didn't work there either so I hacked in a patch that set the property when a checkbox state changed. (Then forgot I had done this)

        private void chkBox_CheckChanged(object sender, RoutedEventArgs e)
        {
            if (sender.GetType() == typeof(CheckBox))
            {
                var temp = (CheckBox)sender;
                switch (temp.Name.ToLower())
                {
                    case "chkprefix":
                        UsePrefix = temp.IsChecked == true;


So if the checkbox that got checked was "chkPrefix" we then changed the UsePrefix property value programmatically. This is very WinForms but works. Isn't the point of WPF binding to get away from doing this? What am I missing?

This post has been edited by tlhIn`toq: 27 June 2012 - 09:45 AM

Was This Post Helpful? 0
  • +
  • -

#6 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Re: Checkbox.IsChecked binding not working as expected

Posted 27 June 2012 - 10:18 AM

Perhaps this is just an oddity to debugging?

With a minor change to my .Checked event handler I notice that the property I'm binding to really does change its value - even though the handler for the property value changing never stops on the breakpoint.

Attached Image

So is this a known behavior in WPF that the methods bound to state changes don't actually execute? I'm guess that what is REALLY happening is the static dependancy property backing field is being changed... and the property get/set method then return that backing field... but the property itself doesn't really execute the get/set methods.

I don't see how this is really helpful in common situations. I had planned to use the method handler for the bool property to trigger a recalculation. Basically the same as .CheckChanged event in WinForms. But if the .IsChecked binding isn't really run and you are forced to subscribe to the Checked and Unchecked methods (to the same handler simulating the .CheckChanged WinForms event that seems like you now have two handlers for the same thing. I could completely removed the binding to the property from the XAML and put it in the check handler method so I have a single reference point to deal with for cleaner maintenance.

I'm sure I have to be missing an important point in the use of WPF binding and handling here. Does anyone grasp what I'm saying?
Was This Post Helpful? 0
  • +
  • -

#7 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Re: Checkbox.IsChecked binding not working as expected

Posted 27 June 2012 - 11:44 AM

I think I found out something interesting, but I posted it in this other thread:
http://www.dreaminco...1&#entry1652771

The two threads should be combined.

But eccentually it looks like the get/set methods of the bound property don't get executed and therefore can't really be used for adding code or for breakpoints... AND therefore they don't really raise PropertyChanged events. Instead in dependency properties the backing field is changed, and the property is just used for get/set access.

Seems like a bug to me.
Was This Post Helpful? 0
  • +
  • -

#8 modi123_1  Icon User is offline

  • Suitor #2
  • member icon



Reputation: 9096
  • View blog
  • Posts: 34,161
  • Joined: 12-June 08

Re: Checkbox.IsChecked binding not working as expected

Posted 27 June 2012 - 11:55 AM

Merged the threads..
Was This Post Helpful? 0
  • +
  • -

#9 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Re: Checkbox.IsChecked binding not working as expected

Posted 27 June 2012 - 11:58 AM

Thanks!
Was This Post Helpful? 0
  • +
  • -

#10 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5481
  • View blog
  • Posts: 11,762
  • Joined: 02-June 10

Re: Checkbox.IsChecked binding not working as expected

Posted 27 June 2012 - 12:04 PM

I beleive I have confirmed that the dependency property doesn't really run the code of the property get/set methods.

When changed to a standard property with backing field it works as expected.

As you can see we no longer need to subscribe to the .Check and .Uncheck events as well as the state of .IsChecked. The property's set method is now executed, breaks at a breakpoint and so on as one would expect.
<CheckBox Name="chkRemoveEnding"
            Margin="5,0,0,0"
            VerticalAlignment="Center"
            Content="Remove ending "
            IsChecked="{Binding UseRemoveEnding,
                                Mode=TwoWay,
                                UpdateSourceTrigger=PropertyChanged}" />




        //public static DependencyProperty UseRemoveEndingProperty = DependencyProperty.Register("UseRemoveEnding",
        // typeof(bool),
        // typeof(ObservedFolderUC),
        // new PropertyMetadata(
        // default(bool)));




        private bool _useremoveending;

        public bool UseRemoveEnding
        {
            //get { return (bool)GetValue(UseRemoveEndingProperty); }
            //set
            //{
            //    SetValue(UseRemoveEndingProperty, value);
            //    RaisePropertyChanged("UseRemoveEnding");
            //}
            get { return _useremoveending; }
            set
            {
                if (_useremoveending != value)
                {
                    _useremoveending = value;
                    RaisePropertyChanged("UseRemoveEnding");
                    Step1_SettingsChanged(null, null);
                }
            }
        }



I guess I need to read more about dependency properties and learn why they work like this and what their true intended purpose is.

This post has been edited by tlhIn`toq: 27 June 2012 - 12:05 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1