19

I have this code behind:

CustomUserControl.xaml.cs

namespace MyProject
{
    public partial class CustomUserControl<T> : UserControl
    {
        ...
    }
}

and this xaml:

CustomUserControl.xaml

<UserControl x:Class="MyProject.CustomUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Grid>

</Grid>

It doesn't work since the x:Class="MyProject.CustomUserControl" doesn't match the code-behind's generic class definition. Is there some way to make this work?

Bob
  • 273
  • 1
  • 3
  • 7

4 Answers4

17

You can create generic "code-behind" file without XAML-file:

public class CustomUserControl<T>: UserControl
{ }

and than derive from it providing specific class as a parameter:

public partial class SpecificUserControl : CustomUserControl<Presenter>
{
    public SpecificUserControl()
    {
        InitializeComponent();
    }
}

XAML:

<application:CustomUserControl 
     x:TypeArguments="application:Presenter"
     xmlns:application="clr-namespace:YourApplicationNamespace"
...

Unfortunately, it seems that Visual Studio designer doesn't support such generics until Visual Studio 2012 Update 2 (see https://stackoverflow.com/a/15110115/355438)

Community
  • 1
  • 1
Ilya Serbis
  • 21,149
  • 6
  • 87
  • 74
11

Haven't found my solution anywhere else so far. The main difference is, that I have got one .xaml file for the generic user control class and not one for each actual user control.

GenericUserControl.xaml.cs

using System.Windows.Controls;

namespace TestGenericUserControl
{
    public abstract partial class GenericUserControl : UserControl
    {
        // If you use event handlers in GenericUserControl.xaml, you have to define 
        // them here as abstract and implement them in the generic class below, e.g.:

        // abstract protected void MouseClick(object sender, MouseButtonEventArgs e);
    }

    public class GenericUserControl<T> : GenericUserControl
    {
        // generic properties and stuff

        public GenericUserControl()
        {
            InitializeComponent();
        }
    }

    // To use the GenericUserControl<T> in XAML, you could define:
    public class GenericUserControlString : GenericUserControl<string> { }
    // and use it in XAML, e.g.:
    // <GenericUserControlString />
    // alternatively you could probably (not sure) define a markup extension to instantiate
    // it directly in XAML
}

GenericUserControl.xaml

<UserControl x:Class="TestGenericUserControl.GenericUserControl"
        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" 
        mc:Ignorable="d">
    <Grid>
        <Label Content="hello" />
    </Grid>
</UserControl>
Tom
  • 171
  • 2
  • 6
  • I kind of see what you're doing, but I'm not the best at XAML architecture. How / where do you specify what the control should look like? I've copied all this code into a test project, but I'm unable to: define what it should look like, how to use this `UserControl` in MainWindow.xaml, and how to bind data to it, e.g. bind `MyGeneric(Of T)` to `Label`'s `Content`. – Zach Mierzejewski May 08 '17 at 14:07
  • @Zach I wrote a little example for you. Have a look at [this](https://github.com/timmi-on-rails/GenericUserControlWPF). – Tom May 09 '17 at 20:54
3

Unfortunately XAML does not support generic code behind, thou you can walk around this.

See links below:

http://forums.silverlight.net/forums/p/29051/197576.aspx

Can I specify a generic type in XAML (pre .NET 4 Framework)?

May be generic controls will be supported natively in future versions of Visual Studuo with XAML 2009.

Community
  • 1
  • 1
angordeyev
  • 511
  • 3
  • 11
0

I ended up with an extra helper class, this is not a UserControl. It does the job well for a simple custom UserControl that needs a Generic Type.

So the UserControl, for instance UCMoveObject, has an InitFunction that returns to me the Helper instance:

// In the UCMoveObjects UserControl Class.
public UCMoveObjectsHelper<T> InitUCMoveObject<T>(List<T> argAllList, List<T> argSelectedList)
{
     return new UCMoveObjectsHelper<T>(this, argAllList, argSelectedList);
}

Then in the helper class I place all the code for making the user control work.

public class UCMoveObjectsHelper<T>
{

public UCMoveObjectsHelper(UCMoveObjects argUserControl, List<T> argAllList, List<T> argSelected)
{
   _ucMoveObjects = argUserControl;

   // Example reaching the usercontrol
   _ucMoveObjects.listBox.SelectionChanged += LbAll_SelectionChanged;

   // Do whatever I want with T
}

public List<T> ReturnSelected()
{
     // Code that return a List<T>;
}

}

In the MainWindow.xaml i place a usercontrol in the window. Then in code I do the following:

  _ucMovingObjectsHelper = ucMovingObjects.InitUCMoveObject<TblUsers>(tempListAll, tempListSelected);

And later in my code I can call:

var tempSelectedList = _ucMovingObjectsHelper.ReturnSelected();
Michiel
  • 67
  • 1
  • 6