Clark
Clark

Reputation: 11

Simple User Control Databinding

I've been trying my hand at creating a simple user control with dependencyproperty and binding it, but it doesn't seem to work, not sure why. I'll just dive straight into code, please ignore the fact that the control doesn't make sense, it's just for illustrative purposes (written in WP8 if that matters).

  1. My simple user control, it's basically a line with a property to turn it off or on.

    <Grid x:Name="LayoutRoot" Background="Transparent">
    <Line Height="105" Width="105" X2="100" Y2="100" Visibility="{Binding LineVisible}" Stroke="#FFFC1515" StrokeThickness="5"/>
    </Grid>
    
    public partial class SimpleUserControl : UserControl
    {
        public SimpleUserControl()
        {
            InitializeComponent();
            DataContext = this;
        }
    
        public static readonly DependencyProperty LineVisibleProperty = DependencyProperty.Register("LineVisible", typeof(bool), typeof(SimpleUserControl), new PropertyMetadata(new PropertyChangedCallback(OnLineVisibleChanged)));
        public bool LineVisible
        {
            get { return (bool)GetValue(LineVisibleProperty); }
            set { SetValue(LineVisibleProperty, value); }
        }
        private static void OnLineVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            bool newvalue = (bool)e.NewValue;
            Visibility vis = newvalue ? Visibility.Visible : Visibility.Collapsed;
            (d as SimpleUserControl).Visibility = vis;
        }
    }
    
  2. The test app

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <uc:SimpleUserControl LineVisible="{Binding class1.Vis}"/>
    </Grid>
    
    public partial class MainPage : PhoneApplicationPage
    {
        public Class1 class1 { get; set; }
        public MainPage()
        {
            InitializeComponent();
            DataContext = this;
        }
        private void PhoneApplicationPage_Loaded_1(object sender, RoutedEventArgs e)
        {
            class1 = new Class1() { Vis = false };
        }
    }
    
  3. The class1 that it's bound to

    public class Class1 : INotifyPropertyChanged
    {
        private bool _vis;
        public bool Vis
        {
            get { return _vis; }
            set
            {
                _vis = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Vis"));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
    

It doesn't seem to work, however, if it is set explicitly like below it works.

<uc:SimpleUserControl LineVisible="False"/>

I'm sure it's something simple, but I'm not seeing it. Thanks for any help.

Upvotes: 0

Views: 116

Answers (2)

Clark
Clark

Reputation: 11

The problem was I was setting the DataContext = this in the UserControl and when binding to Vis in the testapp, it would override and search for Vis in the UserControl (which of course does not exist there). I did see binding errors in the debug output window which confirms this. The solution was to set the LayoutRoot of the UserControl to this as was mentioned in the link I posted earlier.

Upvotes: 1

Chrisjan Lodewyks
Chrisjan Lodewyks

Reputation: 1182

The Visibility property of WPF controls does not use bool values, it requires the Visibility enum. Thus you have two options:

  1. Change LineVisibiltyProperty to Visibility instead of bool.
  2. Use a converter to bind to bool and convert to Visibility.

I would suggest using the second option as this in my opinion is the better solution.

This might be helpful.

Upvotes: 0

Related Questions