d:具有接口类型的DesignInstance

我将UI绑定到接口(由几个演示者实现,无法从UI程序集访问)。

我非常喜欢d:DesignInstance在设计器中,因为它(有点)使得xaml使用R#强类型化。

遗憾的是,d:DesignInstance不支持接口类型:“无法创建接口实例”。

界面上的设计实例

我想到的第一件事是:好的,没问题,让我们创建一个自定义标记扩展,它将System.Type作为参数,以及哪个ProvideValue方法返回它的假实例(此接口的虚拟实现,由动态IL发射生成) 。

这很好用,绑定在设计时解决(我可以在设计面板中看到,因为我的标记扩展用lorem-ipsum填充对象属性)

最好的R#function不起作用:Resharper无法识别datacontext类型,只是在“object”类型的数据上下文中给出了“无法解析属性'{0}”的消息

自定义标记扩展

有人知道如何解决这个问题吗?

(允许我让R#了解接口datacontext类型的任何替代方案都会很棒)

谢谢 !

ps:我还尝试创建另一个标记扩展,它返回生成的运行时类型,以便将其提供给DesignInstance:“{d:DesignInstance Type = {utilsUi:InstanceType commons:User}}”=>给出错误“对象的类型“InstanceType”无法转换为“System.Type”类型“……似乎DesignInstance不支持内部标记扩展:(

我刚刚调查过或多或少相同的问题……实际上,我所做的是遵循MvvMLight的原则。 确切地说,我使用了ViewModelLocator(它或多或少是静态的),以便在运行时或设计时注入“正确的”ViewModel。 神奇之处在于MvvMLight框架提供的函数ViewModelBase.IsInDesignModeStatic 。 最后,我的ViewModelLocator类看起来像

 public class ViewModelLocator { private static readonly IKernel _kernel; static ViewModelLocator() { _kernel = new StandardKernel(); if (ViewModelBase.IsInDesignModeStatic) { _kernel.Bind().To(); } else { _kernel.Bind().To(); } } public IBasicVM BasicVm { get { return _kernel.Get(); } } } 

您可以忽略Ninject _kernel,但如果您使用IoC构建ViewModel,则可能需要它(或类似的Ioc)。

App.xaml将ViewModelLocator声明为ressource

       

MainWindow.DataContext属性绑定到ViewModelLocatorBasicVM成员。 Text属性绑定到接口IBasicVMGetContent成员,该成员由R#静态识别(至少R#7.1与VS2012)

      

您可以将我创建的存储库作为模板进行检查。

在这种情况下,您可以利用IsDesignTimeCreatable,如下所示:

 d:DataContext="{d:DesignInstance commons:User, IsDesignTimeCreatable=False}" 

这实际上指示设计者仅使用类型进行智能感知和错误突出显示,而不是实际尝试实例化设计实例。

我已经发现如何克服这个不合逻辑的Visual Studio XAML设计器错误。

代替

    

你可以写

       

是的,这个解决方案看起来并不酷,但绝对不会更糟。

Type标签允许指定接口,嵌套类型(例如n:A + B)甚至generics!

如果是generics,只需在类型中添加一个反引号和多个类型参数:

BTW所有这些也适用于样式, 不会产生错误!

@Olivier:这是您可以使用“适配器设计模式”的最佳场景之一

注意:我不知道Resharper,我是C#和.NET开发人员。 但我知道根据您的解释存在兼容性问题。 以下是您可以尝试的可能解决方案。

  1. 编写一个实现所需接口类型的C#类。
  2. 在类中实现接口但是不要自己编写整个实现。 而是调用在实现的方法中实现接口的其他类方法。
  3. 开始使用你编写的类。
  4. 为了获得兼容性而编写的类称为Adapter。

示例代码:

 class Program { static void Main(string[] args) { // create an object of your adapter class and consume the features. AdapterInterfaceUI obj = new AdapterInterfaceUI(); // Even though you have written an adapter it still performs the operation in base class // which has the interface implementation and returns the value. // NOTE : you are consuming the interface but the object type is under your control as you are the owner of the adapter class that you have written. Console.WriteLine(obj.DisplayUI()); Console.ReadKey(); } } #region code that might be implemented in the component used. public interface IinterfaceUI { string DisplayUI(); } public class ActualUI : IinterfaceUI { //Factory pattern that would be implemented in the component that you are consuming. public static IinterfaceUI GetInterfaceObject() { return new ActualUI(); } public string DisplayUI() { return "Interface implemented in ActualUI"; } } #endregion #region The adapter class that you may need to implement in resharper or c# which ever works for you. public class AdapterInterfaceUI : ActualUI, IinterfaceUI { public string DisplayUI() { return base.DisplayUI(); } } #endregion 

我认为这个解决方案会帮助你。