0

I need that when clicking on UserControl in TextBlock Visibility changed depending on what value is IsChecked

I wanted to make my checkbox but I ran into such a problem. System.NullReferenceException: "The object reference does not point to an instance of the object." in the OnPropertyChanged method. The logic of this control is that when you click Visibility on it, TextBlock should become either Hidden or Visible (depends on IsChecked value). If I do not write OnPropertyChanged ("IsChecked"); then when the click does not crash, but nothing happens.

UserCheckBox.xaml.cs

public partial class UserCheckBox : UserControl
{
    public UserCheckBox()
    {
        InitializeComponent();
        DataContext = this;
        MouseUp += delegate (object sender, MouseButtonEventArgs e)
        {
            this.IsChecked = true;
        };
    }

    private bool _IsChecked = false;
    public bool IsChecked
    {
        get { return _IsChecked; } private set { _IsChecked = value; OnPropertyChanged("IsChecked"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

UserCheckBox.xaml

<UserControl x:Class="COP.UserCheckBox"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:COP"
         mc:Ignorable="d" 
         d:DesignHeight="30" d:DesignWidth="30" Background="#707070" Name="mainCheckBox">
<UserControl.Resources>
    <local:VisibilityConvert x:Key="Convert"></local:VisibilityConvert>
</UserControl.Resources>
<Border BorderThickness="2" BorderBrush="Black">
    <Grid>        
    <TextBlock FontFamily="Segoe UI Symbol" Text="&#xE10B;" Visibility="{Binding ElementName=mainCheckBox, Path=IsChecked, Converter={StaticResource Convert}}"></TextBlock>
</Grid>
</Border>

VisibilityConvert.cs

class VisibilityConvert : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value == true ? Visibility.Visible : Visibility.Hidden;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
  • This is NOT a duplicate of NullReferenceException question, the OP clearly has a different problem that leads to a null reference exception and simply them learning about what that is doesn't help them solve the problem. It's really disappointing to see that people don't seem to want to address the questioner at all, but instead just get quick points. – Shahin Dohan Sep 27 '18 at 20:09

1 Answers1

0

Your UserControl has to use the INotifyPropertyChanged interface, otherwise WPF doesn't know to listen to this class.

Do this:

public partial class UserCheckBox : UserControl, INotifyPropertyChanged

Also, your IsChecked setter is private when it should be public, otherwise you can't set the property.

Another thing to note, is that you can't use Binding on this property because it's not a Dependency Property so you can only set it in XAML like so IsChecked="True". You might want to create a Dependency Property instead, read this article.

EDIT:

Since I had IsChecked="True" while testing your code OP, I forgot that you also need to subscribe to a left mouse click event, do this on your UserControl XAML:

MouseLeftButtonDown="OnMouseLeftButtonDown" Background="Transparent"

Then create the method in your UserControl.xaml.cs:

private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    IsChecked = !IsChecked;
}

The reason for the Transparent background is to enable click events on the entire area of the UserControl.

All of this being said, I highly suggest you ditch this whole thing. You're much better off learning how to style an existing Checkbox control rather than creating your own.

Community
  • 1
  • 1
Shahin Dohan
  • 4,247
  • 1
  • 29
  • 46
  • Thank you very much for your help, you have helped me a lot. Adding INotifyPropertyChanged and there was an answer to my question. Both IsChecked = "True" did not quite understand. – Павел Ериков Sep 27 '18 at 20:36
  • You still can't rely on PropertyChanged always being non-null. Call `PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name))` instead of `PropertyChanged(this, new PropertyChangedEventArgs(name))` – Clemens Sep 27 '18 at 20:48
  • @Clemens you're right, there are many more things I would change in OP's code, but I tried to answer his/her specific problem. @Павел Ериков I just said that when I was testing your code, I instantiated your UserControl like so `` to test what happens and forgot to remove it so I missed the fact that clicks didn't work at all, and I also said that you can't do `` because IsChecked is not a Dependency Property. Binding is a very fundamental part of WPF, you should use it. – Shahin Dohan Sep 27 '18 at 20:54