locked
How to create a UserControl to be used as a base class? RRS feed

  • Question

  • I am using VS 2008, .Net 3.5, and C#.

    In the abstract, I need to make several UserControls that have similar overall appearance but different specific sets of controls.  However, a lot of the code-behind will be identical.  So it seems like the correct thing to do would be to place all of the common code into a base class that my UserControls would inherit from.  It would be nice if the base class derived from UserControl itself so that it would have a xaml file that could contain reusable declarations and possibly the main containers like GroupBoxes.  The derived classes would add in the specific controls and containers as needed as well as any specific event handlers (Click, SelectionChanged, etc.).

    I tried using VS 2008 to create the following:

    1. Add UserControlBase (.xaml and .xaml.cs) - Use VS to add a new UserControl.
    2. Add UserControlOne (.xaml and .xaml.cs) - Use VS to add a new UserControl.
    3. Edit the UserControlOne to derived from UserControlBase instead of UserControl.
    4. Build fails: Partial declarations of 'Agilent.PXIeRf.ApexModuleControl.UserControlOne' must not specify different base classes.
    5. I tried several things to resolve the error but nothing I tried worked.

    Is there a way to do this?  Is there a better approach?

    Thanks.


    Dave R&D SW Engineer Agilent Technologies
    Friday, February 25, 2011 10:44 PM

Answers

  • To clarify are you trying to inherit the visual element that exist in XAML, like you can do in WinForms?  If so you cannot do this in WPF.  There is no Visual inheritence in WPF.

    Now if you aren't trying to inherit visual element it is easy.  First create your UserControlBase class and add you event handler.  Keep in mind this base class can not have any XAML associated with it.  Code only

      public class MyUserControlBase : UserControl
      {
        public MyUserControlBase()
        {
    
        }
    
        protected virtual void Button_Click(object sender, RoutedEventArgs e)
        {
    
        }
      }
    

    Now create another UserControl that does have a xaml counter part.  Now you will need to change the root elemtn in the XAML to your base class like this:

    <local:MyUserControlBase x:Class="WpfApplication7.MyUserControl"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:local="clr-namespace:WpfApplication7">
      <Grid>
        <Button Click="Button_Click">My Button</Button>
      </Grid>
    </local:MyUserControlBase>
    

    And don't forget the code behind:

      public partial class MyUserControl : MyUserControlBase
      {
        public MyUserControl()
        {
          InitializeComponent();
        }
      }
    

    Notice the button in the derived user control is calling the Button_Click event handler we defined in the base class.  That is all you need to do.

    • Proposed as answer by Brian LagunasMVP Wednesday, March 2, 2011 10:05 PM
    • Marked as answer by Min Zhu Thursday, March 3, 2011 2:03 AM
    Wednesday, March 2, 2011 9:42 PM
  • Hi Dave,

    I think the error is because the mismatch of the partial classes. You will need to change both the xaml and code-behind file for the derived type and they must match.

    Cornel's link shows a limitation of what you want to accomplish: If you want to derive UserControlOne from UserControlBase, then UserControlBase must NOT have a xaml file.

    I suggest you to check out Control Authoring Overview and see what can satisfy your needs.

    If you have any questions or concerns about this issue, please feel free to let me know.

    Have a nice day!


    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Min Zhu Thursday, March 3, 2011 2:04 AM
    Monday, February 28, 2011 8:16 AM
  • Okay, I seem to have a very simple example working.

    In UserControlBase.cs:
    
    using System.Windows;
    using System.Windows.Controls;
    
    namespace DerivedUserControlApp
    {
      public class UserControlBase : UserControl
      {
       protected UserControlBase()
       {}
    
       protected void Button_Click( object sender, RoutedEventArgs e )
       {
         MessageBox.Show( "UserControlBase.myBtnMethod() called." );
       }
      }
    }
    
    In UserControlOne.xaml.cs:
    
    namespace DerivedUserControlApp
    {
      public partial class UserControlOne : UserControlBase
      {
       public UserControlOne()
       {
         InitializeComponent();
       }
      }
    }
    
    
    In UserControlOne.xaml:
    
    <local:UserControlBase x:Class="DerivedUserControlApp.UserControlOne"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:DerivedUserControlApp"
      Height="300" Width="300">
      <Grid>
       <Button Content="Test" HorizontalAlignment="Center" VerticalAlignment="Center" 
           MinHeight="30" MinWidth="60" Click="Button_Click"/>
      </Grid>
    </local:UserControlBase>
    
    In Window1.xaml:
    
    <Window x:Class="DerivedUserControlApp.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:DerivedUserControlApp"
      Title="Window1" Height="300" Width="300">
      <Grid>
       <local:UserControlOne HorizontalAlignment="Center" VerticalAlignment="Center"/>
      </Grid>
    </Window>
    
    
    using System.Windows;
    
    namespace DerivedUserControlApp
    {
      public partial class Window1 : Window
      {
       public Window1()
       {
         InitializeComponent();
       }
      }
    }
    
    

    So now I have a basic framework for inherting the event handler implementations in multiple derived user controls.

    Thanks for the help.


    Dave R&D SW Engineer Agilent Technologies
    • Marked as answer by Min Zhu Thursday, March 3, 2011 2:03 AM
    Wednesday, March 2, 2011 10:03 PM

All replies

  • Hello Dave,

    To derive from a custom UserControl, please read this article: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/fe35716b-2f27-4c39-95a9-a431c0381d47/


    Cornel Croitoriu - Senior Software Developer & Entrepreneur

    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    CWS SoftwareBiz-Forward.comCroitoriu.NET

    Saturday, February 26, 2011 3:02 AM
  • Hi Dave,

    I think the error is because the mismatch of the partial classes. You will need to change both the xaml and code-behind file for the derived type and they must match.

    Cornel's link shows a limitation of what you want to accomplish: If you want to derive UserControlOne from UserControlBase, then UserControlBase must NOT have a xaml file.

    I suggest you to check out Control Authoring Overview and see what can satisfy your needs.

    If you have any questions or concerns about this issue, please feel free to let me know.

    Have a nice day!


    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Min Zhu Thursday, March 3, 2011 2:04 AM
    Monday, February 28, 2011 8:16 AM
  • Hi Dave,

    Just checking in to see if the information was helpful. Please let us know if you would like further assistance.

    Have a great day!


    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, March 2, 2011 2:44 AM
  • There is no visual inheritence in WPF so it is not possible to do what you are trying to do.
    Wednesday, March 2, 2011 4:44 AM
  • The post from Yi-Lun Luo within the provided article contains a broken link: this post.  So I was unable to get any help there. :-(
    Dave R&D SW Engineer Agilent Technologies
    Wednesday, March 2, 2011 9:18 PM
  • I am still not understanding how to solve this issue.  I believe these are my minimum requirements:

    • A common base class that contains protected control event handlers (like click handlers.)
    • Two or more derived UserControls that inherits from the common base class.
    • The controls defined in the derived UserControl use the control event handlers defined in the base class.

    What set of files do I need to accomplish this (*.cs and *.xmal and *.xaml.cs)?

    What modifications need to be made in the xaml files to handle the inheritance.

    Thanks for any help.

     


    Dave R&D SW Engineer Agilent Technologies
    Wednesday, March 2, 2011 9:29 PM
  • To clarify are you trying to inherit the visual element that exist in XAML, like you can do in WinForms?  If so you cannot do this in WPF.  There is no Visual inheritence in WPF.

    Now if you aren't trying to inherit visual element it is easy.  First create your UserControlBase class and add you event handler.  Keep in mind this base class can not have any XAML associated with it.  Code only

      public class MyUserControlBase : UserControl
      {
        public MyUserControlBase()
        {
    
        }
    
        protected virtual void Button_Click(object sender, RoutedEventArgs e)
        {
    
        }
      }
    

    Now create another UserControl that does have a xaml counter part.  Now you will need to change the root elemtn in the XAML to your base class like this:

    <local:MyUserControlBase x:Class="WpfApplication7.MyUserControl"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:local="clr-namespace:WpfApplication7">
      <Grid>
        <Button Click="Button_Click">My Button</Button>
      </Grid>
    </local:MyUserControlBase>
    

    And don't forget the code behind:

      public partial class MyUserControl : MyUserControlBase
      {
        public MyUserControl()
        {
          InitializeComponent();
        }
      }
    

    Notice the button in the derived user control is calling the Button_Click event handler we defined in the base class.  That is all you need to do.

    • Proposed as answer by Brian LagunasMVP Wednesday, March 2, 2011 10:05 PM
    • Marked as answer by Min Zhu Thursday, March 3, 2011 2:03 AM
    Wednesday, March 2, 2011 9:42 PM
  • Okay, I seem to have a very simple example working.

    In UserControlBase.cs:
    
    using System.Windows;
    using System.Windows.Controls;
    
    namespace DerivedUserControlApp
    {
      public class UserControlBase : UserControl
      {
       protected UserControlBase()
       {}
    
       protected void Button_Click( object sender, RoutedEventArgs e )
       {
         MessageBox.Show( "UserControlBase.myBtnMethod() called." );
       }
      }
    }
    
    In UserControlOne.xaml.cs:
    
    namespace DerivedUserControlApp
    {
      public partial class UserControlOne : UserControlBase
      {
       public UserControlOne()
       {
         InitializeComponent();
       }
      }
    }
    
    
    In UserControlOne.xaml:
    
    <local:UserControlBase x:Class="DerivedUserControlApp.UserControlOne"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:DerivedUserControlApp"
      Height="300" Width="300">
      <Grid>
       <Button Content="Test" HorizontalAlignment="Center" VerticalAlignment="Center" 
           MinHeight="30" MinWidth="60" Click="Button_Click"/>
      </Grid>
    </local:UserControlBase>
    
    In Window1.xaml:
    
    <Window x:Class="DerivedUserControlApp.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:DerivedUserControlApp"
      Title="Window1" Height="300" Width="300">
      <Grid>
       <local:UserControlOne HorizontalAlignment="Center" VerticalAlignment="Center"/>
      </Grid>
    </Window>
    
    
    using System.Windows;
    
    namespace DerivedUserControlApp
    {
      public partial class Window1 : Window
      {
       public Window1()
       {
         InitializeComponent();
       }
      }
    }
    
    

    So now I have a basic framework for inherting the event handler implementations in multiple derived user controls.

    Thanks for the help.


    Dave R&D SW Engineer Agilent Technologies
    • Marked as answer by Min Zhu Thursday, March 3, 2011 2:03 AM
    Wednesday, March 2, 2011 10:03 PM
  • Hi Dave,

    I’m glad to hear that you got it working. 

    Thank you for sharing your experience with us. It is very beneficial for other community members having the similar questions.

    Have a nice day!


    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, March 3, 2011 2:03 AM