C# 带有控件/UserControls的依赖项注入/StructureMap
目前,我的C# 带有控件/UserControls的依赖项注入/StructureMap,c#,wpf,structuremap,C#,Wpf,Structuremap,目前,我的应用程序使用UserControls表示我可以浏览的页面。现在我想用依赖项注入扩展现有功能,就像在存储库中使用的那样 所以我的问题是,如何处理用户控件内部使用的控件(在我的情况下代表一个页面),使用依赖项注入模式。如果我有以下控件: public class CustomControl : Control { /// <summary> /// Enable or disable the sidebar feature /// </summar
应用程序
使用UserControl
s表示我可以浏览的页面。现在我想用依赖项注入扩展现有功能,就像在存储库中使用的那样
所以我的问题是,如何处理用户控件内部使用的控件
(在我的情况下代表一个页面),使用依赖项注入
模式。如果我有以下控件
:
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);
}
}
第二种解决方案?
ICustomControlBackend
接口
在UserControl
的构造函数中实例化,并绑定到它的属性
。然后将此属性
绑定到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
{
bool SidebarEnabled{get;}
使某些FancyOperation()无效;
}
公共类CustomerBackEnd:ICustomControlBackend
{
公共bool SidebarEnabled=>false;
public void SomeFancyOperation()
{
MessageBox.Show(“你好世界”);
}
}
公共类CustomerBackend:ICustomControlBackend
{
公共bool SidebarEnabled=>true;
public void SomeFancyOperation()
{
//忽略
}
}
公共类CustomControl:控件
{
///
///启用或禁用侧栏功能
///
公共场所
{
获取{return(bool)GetValue(SidebarEnabledProperty);}
set{SetValue(SidebarEnabledProperty,value);}
}
///
///财产的从属关系。
///
public static readonly dependencProperty SidebarEnabledProperty=dependencProperty.Register(“SidebarEnabled”、typeof(bool)、typeof(CustomControl)、new PropertyMetadata(false));
公共海关管制()
{
DefaultStyleKey=typeof(CustomControl);
}
公共图书馆
{
}
}
公共部分类CustomControlView
{
公共布尔值为{get;}
专用只读ICustomControlBackend\u ControlBackend;
公共CustomControlView()
{
初始化组件();
_ControlBackend=BootstrapperBase.Container.GetInstance();
IsSidebarEnabled=_ControlBackend.SidebarEnabled;
}
}
ICustomControlBackend
实现将在应用程序中执行,而不是在库中执行(在库中执行CustomControl
和CustomControlView
)。因此,我可以通过依赖项注入
更改我的CustomControl
的行为。这是我应该走的路,还是有更好的解决方案呢?作为一种依赖注入控件是很难得的。在桌面应用程序中,它不是非常有用
考虑注入所依赖的视图。
数据将通过viewmodel和不属于视图的模型提供,并且应通过绑定松散耦合。
样式化和模板化可以通过资源字典实现,资源字典不属于视图的一部分,可以合并。
如果使用viewmodel第一个基于模板的视图创建,那么最终作为子视图的内容可以在资源字典中定义
在这种情况下,您可能需要注入完全不同的UI,即向多个客户端销售软件包。如果一个用户界面与另一个用户界面有本质上的不同,那么我会使用不同的项目,从而为不同的用户界面使用dll。
从客户机B向客户机a交付一个完全不同的dll,每个客户机都从其dll获取其X版本。不需要di,您只给客户一个他们付费的代码,客户B代码他们付费
类似地,如果希望外观有所改变,那么可以使用模板并交付不同的资源字典。客户端A获得一个带有蓝色控件的资源字典。客户端B获得一个带有红色控件的资源字典。更常见的是,这将是用于品牌和本地化的图像或语言资源
阅读say PRISM上的文档,您可能会认为通过发现dll完全动态地构建应用程序是大多数应用程序应该如何工作的。
我做过,做过很多大的项目。
一旦这些都成熟了,很明显我们已经实现的组合的最终灵活性就没有意义了。
没有人真的想要那个,它真正增加的只是复杂性
在这种上下文中如何设置属性的答案通常在资源字典中,但绑定也是一种可能性
切换viewmodels中的功能是另一个故事,您可能希望在其中查看接口。即使如此,通常只将数据提供给viewmodel而不是viewmodels本身是最合适的
这是我在许多项目中的实践经验。我不理解你的问题。SidebarEnabled属性始终绑定到TopPropertyFromSecureUserControlPageViewModel源属性。你在问如何设置这个属性(源属性)?我的问题是如何通过依赖项注入来更改控件的属性。例如:CustomerA已被禁用(true),CustomerB未被禁用(false)。所有控件都位于library.dll中,并且仅包含在每个客户的应用程序中。现在我想通过从/app外部注入依赖项来更改library.dll内部控件的属性(等)。您可以通过设置源属性来更改它们。这与依赖注入无关,不过…@mm8我添加了两种解决方案。也许现在你明白我想做什么了。
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();
}
}
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 >