10

I have built a User Control composed, as usual, of a XAML part and a code-behind part. Now, I need to create another User Control which shares some of the functionalities of the former, but which has different looks and might also have additional features in the code-behind.

My first idea was to create an interface to gather the common functionalities of the two types of controls. Is this the right way to go? And how would I manage the different XAML parts I should have? Any advice is welcome.

Tilvia
  • 261
  • 1
  • 4
  • 14
  • It sounds like the codebehind is the problem and not the control. – Ritch Melton Nov 20 '11 at 16:56
  • Ritch, what do you mean? – Tilvia Nov 20 '11 at 17:01
  • 1
    It sounds like you want to change the visuals, but use the same behavior or add to it. The fact that all that behavior code is trapped in code-behind and unavailable for reuse is causing a problem. Are you familiar with presenter patterns, such as MVVM? – Ritch Melton Nov 20 '11 at 17:05
  • Precisely! No, I am quite a beginner... – Tilvia Nov 20 '11 at 17:06
  • 1
    Google MVVM and WPF. The basic idea is that you have a 'ViewModel' that represents view state (probably what you have in codebehind) and is reusable with different views. The usual approach is to wire them together via databinding. Good luck. – Ritch Melton Nov 20 '11 at 17:27

3 Answers3

8

I would like to add another contribution which I think might be useful to others encountering my same situation.

One other possible solution, which in my opinion is suitable if the controls you are going to create are not particularly complex, is to create a base User Control containing the common features that you want to share: such control will be written entirely in C#. This, in fact, allows inheritance in User Controls composed of both XAML and code behind. In the XAML of the inherited control, rather than having

<UserControl> ... </UserControl>

You will have

<MyProject: MyBaseControl x:Class="MyProject.MyExtendedControl"> ... </MyProject: MyBaseControl>

and then in the code behind you will also need to specify the following:

class MyExtendedControl : MyBaseControl

Hope this helps.

Tilvia
  • 261
  • 1
  • 4
  • 14
  • I don't think this is the way to go. When I tried this, I got the error: xyz cannot be the root of a XAML file because it was defined using XAML error. Microsoft describes [here](https://learn.microsoft.com/en-US/troubleshoot/developer/dotnet/framework/general/error-mc6017-define-class-xaml) how to derive from a XAML generated class. – ffonz Feb 05 '22 at 13:25
2

User controls don't lend themselves well to inheritance in WPF, you can do some hacks to make it work, but overall you'll probably be better off using a Custom Control instead. It's easier to specify different XAML for inherited controls using this technique. The easiest way to get started with a custom control is to add a new item to your project of type "Custom Control (WPF)" and it will add the control and the XAML gets added to Themes/generic.xaml for you.

To inherit from this control, the easiest way is to add another new Custom Control (WPF) and then change the code behind to inherit from your parent control instead of Control.

Bill Reiss
  • 3,460
  • 1
  • 19
  • 20
  • So, if I understand correctly, your suggestion is that I should have two custom controls inheriting from a third one which contains the common features? – Tilvia Nov 20 '11 at 16:40
  • 1
    Yes that's correct, another option if you only have a couple of common features is to keep using UserControls and use attached properties or behaviors for the common features – Bill Reiss Nov 20 '11 at 19:15
2

There are a number of ways to split up the pieces to make them easier to work with.

MVVM, as mentioned in a comment, relies upon Data Binding to separate the input controls from logic. By setting the appropriate class which implements INotifyPropertyChanged into the DataContext of you control, you can change the behaviour. Your DataContext class or ViewModel could implement Visibility properties to show and hide different parts of the input if the differences are not too great between the uses.

Another way to break apart functionality is by Aggregation. See StackOverflow 269496

You could build smaller controls that implement common functionality and then build larger special purpose controls by combining the smaller controls (i.e. aggregating them) to make the larger control. Aggregation will work for both the code-behind and the Data Binding approaches.

Community
  • 1
  • 1
Doug Ferguson
  • 2,538
  • 2
  • 16
  • 23