6

Using:

  • Visual Studio Community Edition 2015
  • .Net 4.0

I've implemented this answer, producing my own CheckBox class complete with an IsChecked DependencyProperty. That property is backed by the IsChecked property on the WPF CheckBox, or would be if it would work. Working would mean my getter and setter are called when the checkbox is toggled.

If I rename my property to IsChecked_temp and modify the XAML to match, it works fine. I think this is a naming conflict, but why doesn't ElementName resolve it? My minimal test case follows.

EDIT 0: I forgot to mention, I get no errors or warnings.

EDIT 1: This answer was initially accepted because it works for the test case, but it's apparently not the entire answer. Applying it to my project (and renaming the CheckBox class to ToggleBox) yields a XamlParseException at every use of the property:

A 'Binding' cannot be set on the 'IsChecked' property of type 'ToggleBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

I'll try to get a minimal test case going to show this.

CheckBox.xaml

<UserControl x:Class="CheckBox_test.CheckBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Name="Self">
    <StackPanel>
        <CheckBox IsChecked="{Binding IsChecked, ElementName=Self}" />
    </StackPanel>
</UserControl>

CheckBox.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace CheckBox_test
{
    public partial class CheckBox : UserControl
    {
        public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register(
             "IsChecked",
             typeof(bool),
             typeof(CheckBox),
             new FrameworkPropertyMetadata(false,
                     FrameworkPropertyMetadataOptions.AffectsRender));

        public bool IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }

        public CheckBox()
        {
            InitializeComponent();
        }
    }
}

MainWindow.xaml

<Window x:Class="CheckBox_test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CheckBox_test">
    <Grid>
        <local:CheckBox />
    </Grid>
</Window>

MainWindow.xaml.cs (for completeness)

using System.Windows;

namespace CheckBox_test
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}
Community
  • 1
  • 1
Grault
  • 974
  • 12
  • 31
  • 1
    Just for test, try to write IsChecked="{Binding Path=IsChecked, ElementName=Self}" – Spawn Oct 29 '15 at 20:50
  • 1
    @Spawn I tried that with and without `_temp` and got the same respective results. Worth a try, though, so thanks. – Grault Oct 29 '15 at 21:00
  • Ok, i'll try tomorrow... Self is not so rare name for UserControl, so it must work. Can you tell, what Visual Studio and .NET version you use? – Spawn Oct 29 '15 at 21:04
  • I've edited those details into the question. – Grault Oct 29 '15 at 21:13
  • Oh, and I get the same (lack of) behavior on .Net 4.5.2. – Grault Oct 29 '15 at 21:14
  • I fail to understand what's the use of this. If you want a CheckBox use a CheckBox, not an UserControl....... You should avoid trying to reinvent the wheel. – Federico Berasategui Oct 29 '15 at 21:42
  • He's just wrapping the checkbox (or any control) in more complex control which is simplified for illustration :) – kirotab Oct 29 '15 at 21:43
  • 2
    @kirotab sounds pretty bad IMO. People conflate the usages of `UserControl` and *custom control*, which are 2 completely different concepts, intended for different use cases. – Federico Berasategui Oct 29 '15 at 21:45
  • @HighCore I've got to confess that I'm one of those people that you speak about. So thank you for reminding me that there is such a thing as `CustomControl`. Definitely something that I needed to do earlier but tomorrow will try to expand my knowledge in the area a bit. – kirotab Oct 29 '15 at 21:55
  • Ditto. I remember encountering `CutomControl` a long time ago and not understanding why it exists. However, that's not really relevant to the question. – Grault Oct 29 '15 at 22:05

1 Answers1

1

Very interesting question (at least for me) so it turns out that there is really a conflict of names when you register your Dependency Property.

I'm not exactly sure if this is an answer but I think you'll find this interesting if you didn't knew or thought about it before.

I've used "CheckBox.IsChecked", but any unique name would suffice probably.

public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register(
         "CheckBox.IsChecked",
         typeof(bool),
         typeof(CheckBox),
         new FrameworkPropertyMetadata(false,
                 FrameworkPropertyMetadataOptions.AffectsRender));

This works without change in the name of your property

public bool IsChecked
{
    get
    {
        return (bool)GetValue(IsCheckedProperty);
    }
    set
    {
        SetValue(IsCheckedProperty, value);
    }
}

When you create names for your dependency properties, you must choose unique names that are not being used for dependency properties or events in any base classes that you inherit from; otherwise, an ArgumentException is thrown during runtime. For more information about dependency properties and activity binding, see Custom Activity Binding Sample and Simple Activity Sample.

https://msdn.microsoft.com/en-us/library/vstudio/ms734499(v=vs.90).aspx

Yet another reminder how big of a noob I am :)

kirotab
  • 1,296
  • 1
  • 11
  • 18
  • This solves my problem, even though I don't seem to satisfy the criteria that the conflicting name is "used for dependency properties or events in any base classes that you inherit from." Kudos for this find. – Grault Oct 29 '15 at 22:09
  • Yep, it was just not working with all the binding types that I've tried without changing the name or making the property a normal one instead of dependency... The material is from .net 3.5 and doesn't have newer version (at least I didn't found one) so maybe there are changes... – kirotab Oct 29 '15 at 22:10
  • No man, I thank you, because I've had terrible issues with some dependency properties that I labeled as "Dark Magic" at the time (seemed so illogical how they behave), so now at least I have one more weapon to try to fight them. – kirotab Oct 29 '15 at 22:12
  • Odd. When I implemented this in my actual project, it didn't take. Looks like I need to build a new question about why this doesn't always work. – Grault Oct 29 '15 at 22:24
  • 1
    Hm, if you change the class name to something 100% unique like "asd" instead of "CheckBox.", if it still doesn't work just unmark the answer and maybe somebody smarter than us will explain. – kirotab Oct 29 '15 at 22:26