Search code examples
c#wpfconstructoruser-controls

how to use dependency property to replace the parameter in the constructor of a UserControl?


I noticed that similar questions have been asked before but I did not find any detailed examples.

I have a winform program, its constructor has a parameter cn:

    public AddFailure(ProSimConnect cn)// constructor in winform
    {
      this.connection = cn;
      InitializeComponent();
      ...
    }

Now I need to simulate it in a UserControl in WPF and put it into MainWindow.

In MainWindow.xaml:

   <Border ...>
   <IOS:Core_System/>
   </Border>

I want to do this but I know I can't because it shouldn't have any parameter:

    public Core_System(ProSimConnect cn)// constructor in UserControl
    {            
        this.cn = connection;
        InitializeComponent();
        ...
    }

Therefore I try to use dependency property:

 public partial class Core_System : UserControl
{
    ProSimConnect connection;

    //dependency property
    public ProSimConnect cn
    {
        get { return (ProSimConnect) GetValue(connectionProperty); }
        set { SetValue(connectionProperty, value); }
    }
    public static readonly DependencyProperty connectionProperty =
        DependencyProperty.Register("cn", typeof(ProSimConnect),typeof(Core_System));

  // constructor in UserControl
  public Core_System()
  {            
      this.connection = cn;
      InitializeComponent();
      ...
  }
      ...
}

It doesn't work - it reports "null" exception. Where am I wrong? Thanks.

This is the function that need to use the parameter in the constructor of the UserControl:

    Failure []getSelectedFailures()
    {
        return cn.getFailures().Where(failure => failure_name.Contains(failure.name)).ToArray();
    }

The location I call it is:

public partial class Core_System : UserControl
{
  ...
    private void button_Engine_1_On_Fire(object sender, RoutedEventArgs e)
    {
       ...
       ArmedFailure.create(getSelectedFailures());
    }
}

Solution

  • A dependency property cannot be set before the constructor has returned.

    You could move any code that uses ProSimConnect from the constructor of the UserControl to a dependency property callback:

    public partial class Core_System : UserControl
    {
        ProSimConnect connection;
    
        //dependency property
        public ProSimConnect cn
        {
            get { return (ProSimConnect)GetValue(connectionProperty); }
            set { SetValue(connectionProperty, value); }
        }
        public static readonly DependencyProperty connectionProperty =
            DependencyProperty.Register("cn", typeof(ProSimConnect), typeof(Core_System), new PropertyMetadata(new PropertyChangedCallback(OnPropertySet));
    
        private static void OnPropertySet(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Core_System ctrl = d as Core_System;
            ctrl.connection = e.NewValue as ProSimConnect;
            //...
        }
    
        // constructor in UserControl
        public Core_System()
        {
            InitializeComponent();
        }
    }
    

    The callback will be invoked whenever the dependency property is set to a value.