带控件/ UserControls的

时间:2018-04-03 08:27:09

标签: c# wpf structuremap

目前我的Application使用UserControl来表示我可以浏览的网页。现在,我希望使用Dependency Injectionhttps://github.com/jpreecedev/WPFMVVMWithStructureMap)中使用的repository扩展现有功能。

所以我的问题是,如何处理Control(在我的情况下代表一个页面)中使用的UserControl来使用Dependency Injection模式。如果我有以下Control

public class CustomControl : Control
{
    /// <summary>
    /// Enable or disable the sidebar feature
    /// </summary>
    public bool SidebarEnabled
    {
        get { return (bool)GetValue(SidebarEnabledProperty); }
        set { SetValue(SidebarEnabledProperty, value); }
    }

    /// <summary>
    /// The <see cref="SidebarEnabled"/> DependencyProperty.
    /// </summary>
    public static readonly DependencyProperty SidebarEnabledProperty = DependencyProperty.Register("SidebarEnabled", typeof(bool), typeof(CustomControl), new PropertyMetadata(false));

    public CustomControl()
    {
        DefaultStyleKey = typeof(CustomControl);
    }
}

示例UserControlPage

<basic:SecureUserControlPage 
    xmlns:Foo="http://foo.com/">
    <Grid>
        <Foo:CustomControl SidebarEnabled="{Binding ToPropertyFromSecureUserControlPageViewModel}"/>
    </Grid>
</basic:SecureUserControlPage >

如何按SidebarEnabled设置Injection属性?我应该将xaml代码中的属性绑定到实际页面的ViewModel,还是可以在interfaces后面的代码中使用CustomControl并在那里设置属性?

第一个解决方案?

ICustomControlBackend interfaceconstructor的{​​{1}}中实例化,并设置Control

property

第二种解决方案?

public interface ICustomControlBackend { bool SidebarEnabled { get; } void SomeFancyOperation(); } public class CustomerABackend : ICustomControlBackend { public bool SidebarEnabled => false; public void SomeFancyOperation() { MessageBox.Show("Hello World"); } } public class CustomerBBackend : ICustomControlBackend { public bool SidebarEnabled => true; public void SomeFancyOperation() { //ignore } } public class CustomControl : Control { /// <summary> /// Enable or disable the sidebar feature /// </summary> public bool SidebarEnabled { get { return (bool)GetValue(SidebarEnabledProperty); } set { SetValue(SidebarEnabledProperty, value); } } /// <summary> /// The <see cref="SidebarEnabled"/> DependencyProperty. /// </summary> public static readonly DependencyProperty SidebarEnabledProperty = DependencyProperty.Register("SidebarEnabled", typeof(bool), typeof(CustomControl), new PropertyMetadata(false)); private readonly ICustomControlBackend _ControlBackend; public CustomControl() { DefaultStyleKey = typeof(CustomControl); _ControlBackend = BootstrapperBase.Container.GetInstance<ICustomControlBackend>(); SidebarEnabled = _ControlBackend.SidebarEnabled; } public void Foo() { _ControlBackend.SomeFancyOperation(); } } ICustomControlBackendinterface的{​​{1}}中实例化,并绑定到constructor。然后,此UserControl会绑定到property的{​​{1}}。

property

property实施将在CustomControl代码中完成,而不是在库中(其中public interface ICustomControlBackend { bool SidebarEnabled { get; } void SomeFancyOperation(); } public class CustomerABackend : ICustomControlBackend { public bool SidebarEnabled => false; public void SomeFancyOperation() { MessageBox.Show("Hello World"); } } public class CustomerBBackend : ICustomControlBackend { public bool SidebarEnabled => true; public void SomeFancyOperation() { //ignore } } public class CustomControl : Control { /// <summary> /// Enable or disable the sidebar feature /// </summary> public bool SidebarEnabled { get { return (bool)GetValue(SidebarEnabledProperty); } set { SetValue(SidebarEnabledProperty, value); } } /// <summary> /// The <see cref="SidebarEnabled"/> DependencyProperty. /// </summary> public static readonly DependencyProperty SidebarEnabledProperty = DependencyProperty.Register("SidebarEnabled", typeof(bool), typeof(CustomControl), new PropertyMetadata(false)); public CustomControl() { DefaultStyleKey = typeof(CustomControl); } public void Foo() { } } public partial class CustomControlView { public bool IsSidebarEnabled { get; } private readonly ICustomControlBackend _ControlBackend; public CustomControlView() { InitializeComponent(); _ControlBackend = BootstrapperBase.Container.GetInstance<ICustomControlBackend>(); IsSidebarEnabled = _ControlBackend.SidebarEnabled; } } <basic:SecureUserControlPage x:Class="LoremIpsum.CustomControlView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:basic="clr-namespace:Foo.Basic" xmlns:loremIpsum="clr-namespace:LoremIpsum"> <Grid> <loremIpsum:CustomControl SidebarEnabled="{Binding IsSidebarEnabled}"/> </Grid> </basic:SecureUserControlPage > ICustomControlBackend已实施)。因此,我可以通过application更改CustomControl的行为。这是我应该采用的方式,还是有更好的解决方案来解决它?

1 个答案:

答案 0 :(得分:-1)

注射控制作为依赖是非常罕见的。它在桌面应用程序中并不是非常有用。

考虑哪些视图依赖于注入。 数据将通过视图模型和模型来实现,视图模型和模型不是视图的一部分,应通过绑定松散耦合。 样式和模板可以通过资源字典来实现,资源字典不是视图的一部分,可以合并。 如果您使用viewmodel第一个基于模板的视图创建,则可以在资源字典中定义最终作为子视图的内容。

您可能想要注入完全不同的UI的情况是出售给多个客户端的软件包。如果一个人需要与另一个人截然不同的UI,那么我将使用不同的项目,因此对于不同的UI片段使用dll。 从客户端B向客户端A完全提供不同的dll,并且每个dll都从其dll获取其X版本。不需要,您只需向客户提供他们支付的代码,他们支付的客户B代码。

同样,如果您希望外观有所改变,那么您可以使用模板并提供不同的资源字典。客户端A获取带有蓝色控件的资源字典。客户端B获取带有红色控件的资源字典。更常见的是,这将是用于品牌推广和本地化的图标或语言资源。

要阅读有关PRISM的文档,您可能会认为通过发现dll是大多数应用程序应该如何工作的动态构建应用程序。 我已经完成了这项工作,参与过非常大的项目。 一旦这些成熟,很明显我们实施的作品的最终灵活性没有任何意义。 没有人真的想要这一点,它真正添加的只是复杂功能。

在此上下文中设置属性的答案通常在资源字典中,但绑定也是可能的。

切换视图模型中的功能是另一个故事,您可能希望查看接口。即便如此,它通常最适合仅提供给视图模型的数据而不是视图模型本身。

无论如何,这是我在许多项目中的实践经验。