【问题标题】:Wpf usercontrol with parameterised constructor带有参数化构造函数的 Wpf 用户控件
【发布时间】:2010-04-30 11:55:20
【问题描述】:

我们正在使用 Microsoft Unity 和依赖注入,因此我们为用户控件设置了参数化构造函数。如何使用 XAML 将此依赖项注入到用户控件中?

我在 XAML 中添加了用户控件,如下所示。

xmlns:usrRefundArrivalProcessor="Ttl.Refunds.Wpf.Dashboad.Application.Usercontrols;assembly=Ttl.Refunds.Wpf.Dashboad.Application"

【问题讨论】:

    标签: wpf user-controls unity-container


    【解决方案1】:

    依赖注入并不意味着参数化的构造函数。事实上,如果你看 Unity 自带的示例,大部分依赖注入都是通过带有 [Dependency] 属性的属性来完成的。

    Unity 与 XAML 配合得很好,但前提是您不使用参数化构造函数。使用具有 [Dependency] 属性的属性转换您的 UserControl 以获取其依赖项,您可以轻松使用 XAML。

    public class MyUserControl : UserControl
    {
      [Dependency]
      public ISomething Something { get; set; }
    
      [Dependency]
      public IWhatever Whatever { get { return (IWhatever)GetValue(WhateverProperty); } set { SetValue(WhateverProperty, value); }
      public readonly DependencyProperty WhateverProperty = DependencyProperty.Register("Whatever", typeof(IWhatever), typeof(MyUserControl));
    
      ...
    }
    

    请注意,[Dependency] 属性可以声明为 DependencyProperty 或普通 CLR 属性,如上所示。这听起来像是令人困惑的命名法,但实际上它非常简单。

    要在 XAML 中指定 UnityContainer 并获得自动配置,只需创建一个继承的附加属性“UnityHelper.Container”,其 PropertyChangedCallback 只需在指定容器上调用 BuildUp 并传入对象的类型和对象:

    public class UnityHelper
    {
      public static IUnityContainer GetContainer(DependencyObject obj) { return (IUnityContainer)obj.GetValue(ContainerProperty); }
      public static void SetContainer(DependencyObject obj, IUnityContainer value) { obj.SetValue(ContainerProperty, value); }
      public static readonly DependencyProperty ContainerProperty = DependencyProperty.RegisterAttached("Container", typeof(IUnityContainer), typeof(UnityHelper), new FrameworkPropertyMetadata
      {
        Inherits = true,
        PropertyChangedCallback = (obj, e) =>
        {
          var container = e.NewValue as IUnityContainer;
          if(container!=null)
          {
            var element = obj as FrameworkElement;
            container.BuildUp(obj.GetType(), obj, element==null ? null : element.Name);
          }
        }
      });
    }
    

    现在您可以将 UnityContainer 分配给您的根窗口,您的整个应用程序都会使用它,例如,您可以在窗口的构造函数中执行以下操作:

    UnityHelper.SetContainer(this, new UnityContainer() ...);
    

    或者您可以使用 XAML 在树的任何所需级别分配统一容器:

    <UserControl ...
      my:UnityHelper.Container="{DynamicResource MainUnityContainer}" />
    

    说了这么多,我想您会发现 WPF 的高级数据绑定功能和资源字典一起消除了人们最初可能想要使用 Unity 的 98% 的原因。从长远来看,您可能会发现离开 Unity 并使用简单的 MVVM 会更好。至少在开发大量依赖 Unity 进行依赖注入的代码之前,我会在测试应用程序上尝试纯 MVVM,看看它是如何工作的。

    【讨论】:

    • 它可以工作,但是当我从其中一个文本框中点击选项卡按钮时,它会引发异常 依赖项解析失败,类型 = "System.Windows.Input.KeyboardNavigation+FocusVisualAdorner", name = " ”。异常消息是:当前构建操作(构建键 Build Key[System.Windows.Input.KeyboardNavigation+FocusVisualAdorner,null])失败:无法从程序集“PresentationFramework,Version=3.0”加载类型“System.Windows.Input.KeyboardNavigation” .0.0,文化=中性,PublicKeyToken=31bf3856ad364e35'。 (策略类型 BuildPlanStrategy,索引 5)
    • 这个答案对我帮助很大。我希望我能给超过+1。我已将此线程添加到“我的收藏夹”中,但这仅归功于提出原始问题的人。所以,谢谢!
    • 如果你创建了一个接口(比如称为 IUnityElement),你将它应用于你需要统一运行的所有 UserControls 或控件,那么在“if(container!=null)”行中你可以检查是否obj 参数属于该接口,例如'如果(容器!= null && obj 是 IUnityInject)'。这消除了 Miral 上面评论的错误(我从不同的对象和性能问题 ZeePrime 的回答中得到了类似的错误,因为 BuildUp 仅在您需要的 FrameworkElements 上运行。
    【解决方案2】:

    看起来很简单。为什么不简单地将“公共无参数构造函数”添加到您的UserControl?您可以选择不在您的代码中直接使用它,但这正是设计器正在寻找的。如果您想确保它永远不会在代码中被调用,请输入a check for presence of Designer 并在未检测到 Designer 时抛出异常。

    【讨论】:

      【解决方案3】:

      它可以工作,但是当您使用网格或复杂的 WPF 屏幕时,性能会很差。 Inherits = true 意味着创建的所有 GUI 元素都将在构造函数之后调用附加属性的 PropertyChangedCallback,即使该特定 GUI 元素根本不需要 Unity。 当您有网格时,每次出现新行时,所有 GUI 元素都会动态创建,并调用该回调。 这会破坏我们网格的性能,因此我们不得不以这种方式移除 UnityInjection。

      但是,尽管我们在代码隐藏中有些地方需要 UnityInjection,但我们还没有找到解决这个问题的好方法,即使我们使用的是 MVVM。 一些复杂的用户控件是使用 MVVM 设计的,其中控件的 ViewModel 是由控件本身的代码隐藏创建的,该代码隐藏是由使用该控件的 XAML 创建的。 在这种特定情况下,控件的 ViewModel 对 Unity 还一无所知,但我们确实需要在其中进行统一注入,以便访问注册的外部资源。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-25
        • 2011-10-09
        • 2011-10-08
        • 1970-01-01
        • 2011-02-28
        相关资源
        最近更新 更多