目前我的Application
使用UserControl
来表示我可以浏览的网页。现在,我希望使用Dependency Injection
(https://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);
}
}
<basic:SecureUserControlPage
xmlns:Foo="http://foo.com/">
<Grid>
<Foo:CustomControl SidebarEnabled="{Binding ToPropertyFromSecureUserControlPageViewModel}"/>
</Grid>
</basic:SecureUserControlPage >
如何按SidebarEnabled
设置Injection
属性?我应该将xaml
代码中的属性绑定到实际页面的ViewModel
,还是可以在interfaces
后面的代码中使用CustomControl
并在那里设置属性?
ICustomControlBackend
interface
在constructor
的{{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();
}
}
ICustomControlBackend
在interface
的{{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
的行为。这是我应该采用的方式,还是有更好的解决方案来解决它?
答案 0 :(得分:-1)
注射控制作为依赖是非常罕见的。它在桌面应用程序中并不是非常有用。
考虑哪些视图依赖于注入。 数据将通过视图模型和模型来实现,视图模型和模型不是视图的一部分,应通过绑定松散耦合。 样式和模板可以通过资源字典来实现,资源字典不是视图的一部分,可以合并。 如果您使用viewmodel第一个基于模板的视图创建,则可以在资源字典中定义最终作为子视图的内容。
您可能想要注入完全不同的UI的情况是出售给多个客户端的软件包。如果一个人需要与另一个人截然不同的UI,那么我将使用不同的项目,因此对于不同的UI片段使用dll。 从客户端B向客户端A完全提供不同的dll,并且每个dll都从其dll获取其X版本。不需要,您只需向客户提供他们支付的代码,他们支付的客户B代码。
同样,如果您希望外观有所改变,那么您可以使用模板并提供不同的资源字典。客户端A获取带有蓝色控件的资源字典。客户端B获取带有红色控件的资源字典。更常见的是,这将是用于品牌推广和本地化的图标或语言资源。
要阅读有关PRISM的文档,您可能会认为通过发现dll是大多数应用程序应该如何工作的动态构建应用程序。 我已经完成了这项工作,参与过非常大的项目。 一旦这些成熟,很明显我们实施的作品的最终灵活性没有任何意义。 没有人真的想要这一点,它真正添加的只是复杂功能。
在此上下文中设置属性的答案通常在资源字典中,但绑定也是可能的。
切换视图模型中的功能是另一个故事,您可能希望查看接口。即便如此,它通常最适合仅提供给视图模型的数据而不是视图模型本身。
无论如何,这是我在许多项目中的实践经验。