【问题标题】:WPF UserControl with generic code-behind带有通用代码隐藏的 WPF UserControl
【发布时间】:2010-09-28 09:03:04
【问题描述】:

我有这段代码:

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" 与代码隐藏的通用类定义不匹配。有什么方法可以让这个工作吗?

【问题讨论】:

    标签: c# .net wpf generics xaml


    【解决方案1】:

    您可以在没有 XAML 文件的情况下创建通用“代码隐藏”文件:

    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 设计器似乎在 Visual Studio 2012 Update 2 之前不支持此类泛型(请参阅https://stackoverflow.com/a/15110115/355438)

    【讨论】:

      【解决方案2】:

      到目前为止,我还没有在其他任何地方找到我的解决方案。 主要区别是,我有一个 .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
      }
      

      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>
      

      【讨论】:

      • 我有点明白你在做什么,但我不是最擅长 XAML 架构的。您如何/在哪里指定控件的外观?我已将所有这些代码复制到一个测试项目中,但我无法:定义它应该是什么样子,如何在 MainWindow.xaml 中使用这个UserControl,以及如何将数据绑定到它,例如将MyGeneric(Of T) 绑定到Label 的Content。
      • @Zach 我为你写了一个小例子。看看this。
      【解决方案3】:

      不幸的是,XAML 不支持后面的通用代码,你可以绕过这个。

      查看以下链接:

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

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

      Visual Studuo 的未来版本可能会原生支持通用控件 XAML 2009。

      【讨论】:

        【解决方案4】:

        我最终得到了一个额外的帮助类,这不是一个用户控件。对于需要通用类型的简单自定义 UserControl,它可以很好地完成工作。

        所以 UserControl,例如 UCMoveObject,有一个 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();
        

        【讨论】:

          猜你喜欢
          • 2013-10-17
          • 2021-12-01
          • 1970-01-01
          • 2010-10-20
          • 2020-04-23
          • 2015-04-01
          • 2011-01-08
          • 2012-03-19
          • 2011-04-21
          相关资源
          最近更新 更多