question

Wanderer-8803 avatar image
0 Votes"
Wanderer-8803 asked ·

WPF UserControl and inheritance (how to?)

Hello

I want create create my own class UserControl and add here all DependencyProperties (for separation and reuse) and then inherit this UserControl in U.C. with Xaml.

for example:

 public class c_knob : UserControl // this control doesn't have xaml
 {
      // ...
 }
    
 public partial class uc_knob1 : c_knob // there was UserControl changed by c_knob, this control have xaml
 {
      public uc_knob1()
      {
           InitializeComponent();
      }
    
 }
    
 <UserControl
             x:Class="MyApp.controls.uc_knob1"
        
              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:MyApp.controls"


Problem with this code is when I build it, it throw this error

error CS0263: Partial declarations of 'uc_knob1' must not specify different base classes



Question is, how to inherit UserControl derived class for UserControl with Xaml?
I found some solution (rewrite UserControl to c_knob in Xaml) but then Visual Studio Designer doesn't show the visual and it looks like error, but code is compiled.

Another question if it is not possible, how to separate DependencyProperties and use it in UserControl with Xaml? Because DependencyProperty object must exist in class derived (at least if I know) with DependencyObject which cannot be inherited for UserControl unfortunately.

windows-wpf
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Wanderer-8803 avatar image
1 Vote"
Wanderer-8803 answered ·

Thanks all for answers, today I resolve it myself. Strange is, it was not working yesterday and today it magicaly working... VS have very strange behavior.

What I done is

 public class c_knob : UserControl // this control doesn't have xaml
  {
       // ...
  }
     
  public partial class uc_knob1 : c_knob // there was UserControl changed by c_knob, this control have xaml
  {
       public uc_knob1()
       {
            InitializeComponent();
       }
     
  }

now the important part is change UserControl to local:c_knob inside XAML. If it is not working, try reload project, or reopen Visual Studio.



  <local:c_knob
              x:Class="MyApp.controls.uc_knob1"
         
               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:MyApp.controls">
·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

LloydSheen-3317 avatar image
0 Votes"
LloydSheen-3317 answered ·

Instead of

x:Class="MyApp.controls.uc_knob1"

try

x:Class="uc_knob1"

· 1 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

It looks like working from Desginer view. That means, no error even on build. But when control is added in to MainWindow, control is not displayed (cannot create control in Designer view), and when I run a app, I got this error:

ArgumentException: Default value type does not match type of property 'b_ValueCurrent'. (b_ValueCurrent is inside c_knob class as DependencyProperty)

PS. I have to delete InitializeComponent(); from uc_knob1 class,othervise I got error CS0103: The name 'InitializeComponent' does not exist in the current context

Edit:
I found error in my code with b_ValueCurrent have initial value 0 instead 0.0 (double). But still it is not working. But I discover that instead

x:Class="MyApp.controls.uc_knob1"

I tried

x:Class="MyApp.controls.c_knob"

which is working, but uc_knob1.cs is then not used, which is not desired effect.



0 Votes 0 ·
PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered ·

Hi, it's impossible inherit one UserControl from another UserControl. Implicitly a WPF UserControl inherits from base class UserControl. In C# you cannot inherit from 2 classes like in C++. For Inheritance you must use CustomControls. On every inheritance level you include design via Style.

Try following demo (base control with DepenencyProperty, inherited control with bounded Label, MainWindow with used property):

Base control:

 using System.Windows;
 using System.Windows.Controls;
    
 namespace WpfControlLibrary1
 {
   public class Window36CC1 : Control
   {
     static Window36CC1()
     {
       DefaultStyleKeyProperty.OverrideMetadata(typeof(Window36CC1), new FrameworkPropertyMetadata(typeof(Window36CC1)));
     }
    
     public Window36CC1()
     {
       this.DataContext = this;
     }
    
     public string Info
     {
       get { return GetValue(InfoProperty).ToString(); }
       set { SetValue(InfoProperty, value); }
     }
    
     public static readonly DependencyProperty InfoProperty =
         DependencyProperty.Register("Info", typeof(string), typeof(Window25UC3),
             new PropertyMetadata(string.Empty));
   }
 }

Inherited control:

 using System.Windows;
    
 namespace WpfControlLibrary1
 {
   public class Window36CC2 : Window36CC1
   {
     static Window36CC2()
     {
       DefaultStyleKeyProperty.OverrideMetadata(typeof(Window36CC2), new FrameworkPropertyMetadata(typeof(Window36CC2)));
     }
   }
 }

And Generic.xaml:

 <ResourceDictionary
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="clr-namespace:WpfControlLibrary1">
    
    
   <Style TargetType="{x:Type local:Window36CC1}">
     <Setter Property="Template">
       <Setter.Value>
         <ControlTemplate TargetType="{x:Type local:Window36CC1}">
           <Border Background="{TemplateBinding Background}"
                             BorderBrush="{TemplateBinding BorderBrush}"
                             BorderThickness="{TemplateBinding BorderThickness}">
           </Border>
         </ControlTemplate>
       </Setter.Value>
     </Setter>
   </Style>
    
   <Style TargetType="{x:Type local:Window36CC2}">
     <Setter Property="Template">
       <Setter.Value>
         <ControlTemplate TargetType="{x:Type local:Window36CC2}">
           <Border Background="{TemplateBinding Background}"
                             BorderBrush="{TemplateBinding BorderBrush}"
                             BorderThickness="{TemplateBinding BorderThickness}">
             <Grid>
               <Label Content="{Binding Info}"/>
             </Grid>
           </Border>
         </ControlTemplate>
       </Setter.Value>
     </Setter>
   </Style>
      
 </ResourceDictionary>

MainWindow:

 <Window x:Class="WpfApp1.Window36"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:WpfApp1"
         xmlns:uc="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
         mc:Ignorable="d"
         Title="Window36" Height="450" Width="800">
   <Grid>
     <uc:Window36CC2 Info="TestText"/>
   </Grid>
 </Window>

Result:

8064-x.png






x.png (5.8 KiB)
·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.