WPF通用代码后台的用户控件

19

我有以下代码:

CustomUserControl.xaml.cs

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

以及这个 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>

x:Class="MyProject.CustomUserControl"与代码后台的泛型类定义不匹配,所以它不起作用。 有没有办法使其正常工作?

4个回答

17

你可以创建不带XAML文件的通用 "code-behind" 文件:

public class CustomUserControl<T>: UserControl
{ }

然后从中派生出来,将特定类作为参数提供:

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

XAML:

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

很遗憾,看起来直到Visual Studio 2012 Update 2,Visual Studio设计器才支持这样的泛型(请参见https://dev59.com/K23Xa4cB1Zd3GeqPfoiq#15110115)。


11

到目前为止,我在其他地方都没有找到解决方案。 主要区别在于,我只有一个.xaml文件用于通用用户控件类,而不是每个实际用户控件都有一个。

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
}

通用用户控件.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>

我有点明白你在做什么,但我不是最擅长XAML架构的人。 你在哪里/如何指定控件的外观?我已经将所有这些代码复制到一个测试项目中,但我无法:定义它应该看起来像什么,如何在MainWindow.xaml中使用此“UserControl”,以及如何将数据绑定到它上面,例如将“MyGeneric(Of T)”绑定到“Label”的“Content”。 - Zach Mierzejewski
@Zach,我为你写了一个小例子。请看这个链接:https://github.com/timmi-on-rails/GenericUserControlWPF。 - Tom

3

0

我最终得到了一个额外的帮助类,它不是一个UserControl,但对于需要使用泛型的简单自定义UserControl而言,它能够胜任工作。

因此,例如UCMoveObject的UserControl具有一个InitFunction,该函数会返回Helper实例:

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

然后在辅助类中,我将所有使用户控件正常工作的代码放置其中。
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>;
}

}

在MainWindow.xaml中,我将一个用户控件放置在窗口中。然后在代码中,我执行以下操作:
  _ucMovingObjectsHelper = ucMovingObjects.InitUCMoveObject<TblUsers>(tempListAll, tempListSelected);

然后在我的代码中,我可以调用:

var tempSelectedList = _ucMovingObjectsHelper.ReturnSelected();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接