我有一个名为Model<T>
的类,它实现IDynamicObjectProvider
并包装类型为T
的对象,转发对基础值的属性访问,同时添加额外的东西(例如{ {1}}实现Model<T>
,而INotifyPropertyChanged
则不实现。
我在WPF中使用这些T
个对象作为Model<T>
的属性,基本上是:
DataContext
public class Person { public string Name { get; set; } }
public class EditPersonViewModel {
public Model<Person> Person { get; set; }
public ICommand SavePersonCommand { get; set; }
}
WPF绑定引擎成功绑定到<StackPanel d:DataContext="{d:DesignInstance vm:EditPersonViewModel}">
<TextBox Text="{Binding Person.Name}" />
<Button Command="{Binding SavePersonCommand}" />
</StackPanel>
动态getter和setter。
现在,当我编写一个以Model<Person>
开头的绑定时,我希望从XAML设计器中Person
类型的属性中自动完成,其方式需要的应用程序代码尽可能少。可能;理想情况下,它可以完全由定义Person.
的库的提供者实现。 (我是编写库的人,我希望我的客户能够尽可能少地使用Model<T>
类。)
以下是我知道的方法,以及我对他们的反对意见:
定义一个新类Model<T>
,它将镜像所有EditPersonViewModelDesign
属性,并将其用作设计实例。
EditPersonViewModel
public class EditPersonViewModelDesign {
public Person Person { get; set; }
public ICommand SavePersonCommand { get; set; }
}
虽然这不需要过多的代码,但是这个类仍然会在运行时保留在库中,除非我要求人们使构建复杂化(他们是否只添加了这些类的项目,或者他们添加了构建变量)与我完全不相容。此外,Design和View模型类更容易分开。
优化内部元素的数据上下文并影响新的设计实例,例如:
<StackPanel d:DataContext="{d:DesignInstance vm:EditPersonViewModelDesign}">
<TextBox Text="{Binding Person.Name}" />
<Button Command="{Binding SavePersonCommand}" />
</StackPanel>
虽然该解决方案不需要创建新类型,但添加的XAML代码对我来说非常具有侵略性。
答案 0 :(得分:3)
我不认为这里确实存在令人满意的解决方案,因为唯一真正的“非解决方法”是IntelliSense对动态绑定目标的本机支持(即{{1}上的GetDynamicMemberNames
调用由DynamicMetaObject
的设计实例的GetMetaObject()
返回。所以,我首先建议feature request。
如果我是您的客户,我不会为了智能感知支持而在任何地方花费定义设计时间绑定。它需要更多思考来指定正确的绑定,而不是记住或查找并键入属性名称。
这是一个可能有效的想法。当然,我还没有对它进行测试,但通过一些研究,它可能会让你在那里。你似乎在知道,你在做什么:
查看Model<T>
中静态DesignerProperties类的IsInDesignTool
属性:
System.ComponentModel
可以在ViewModel中实现一种DesignerProperties.IsInDesignTool
方法here。这可能是一种返回内部模型(类型为T)的方法,而不是包装模型(Model)。不确定它是否能让你随处可见,但是考虑它可能是值得的。无论如何,这是一个有趣的特征......
最后的想法:通过发送代码片段来改善用户体验,并想出一种区分设计时绑定和运行时绑定的直观方法。也许是这样的:
if DesignMode do this, else do that
创建
的代码段public abstract class ViewModelBase<T>
{
public Model<T> Model { get; }
// Maybe use compiler directives to throw exception if requested at runtime
public T DesignModel { get; }
}
不知道,VS代码片段有多强大,因为我正在使用ReSharper,但是使用ReSharper,您可以使控件的DP变为d:Text="{Binding DesignModel.Name}" Text="{Binding Model.Name}"
,属性名称为变量{{1 }}。然后,IntelliSense将处理设计时绑定,并且如果您按Enter键,则会自动将属性名称复制到第二个绑定。
您可以输入一些快捷方式$ControlProp$
,然后输入$PropName$
,输入,pbind
,这将触发IntelliSense,选择Text
,输入。完成。至少很容易。
底线:我没有对你的问题的即插即用答案,但我的观点可能对某些灵感有益......至少我希望如此。