简体   繁体   English

编写绑定时,如何提供供Visual Studio XAML设计器使用的自定义属性名称列表?

[英]How to provide a list of custom property names for use by the Visual Studio XAML Designer when writing Bindings?

I have a class, called Model<T> , that implements IDynamicObjectProvider and wraps an object of type T , forwarding property access to an underlying value, while adding extra stuff (eg, Model<T> implements INotifyPropertyChanged whereas T does not). 我有一个名为Model<T>的类,该类实现IDynamicObjectProvider并包装类型为T的对象,将属性访问转发给基础值,同时添加其他内容(例如, Model<T>实现INotifyPropertyChangedT不实现)。

I use these Model<T> objects as properties of my DataContext in WPF, essentially: 我将这些Model<T>对象用作WPF中DataContext属性,本质上是:

public class Person { public string Name { get; set; } }

public class EditPersonViewModel {
    public Model<Person> Person { get; set; }
    public ICommand SavePersonCommand { get; set; }
}
<StackPanel d:DataContext="{d:DesignInstance vm:EditPersonViewModel}">
    <TextBox Text="{Binding Person.Name}" />
    <Button Command="{Binding SavePersonCommand}" /> 
</StackPanel>

The WPF Binding engine binds to Model<Person> dynamic getters and setters successfully. WPF绑定引擎成功绑定到Model<Person>动态获取器和设置器。

Now, I would like to get auto-completion from the Person type's properties in the XAML designer when I write a binding that starts with Person. 现在,当我编写以Person.开头的绑定时,我想从XAML设计器中Person类型的属性中自动完成Person. , in a way that requires as little application code as possible; ,从而需要尽可能少的应用程序代码; ideally, it would be entirely implementable by the provider of the library that defines Model<T> . 理想情况下,它可以完全由定义Model<T>的库提供程序实现。 (I am the one that writes the library and I would like my clients to be able to use the Model<T> class with as little fuss as possible). (我是写该库的人,我希望我的客户能够尽可能少地使用Model<T>类)。

Here are the ways that I know would work, and my objections to them: 以下是我知道的工作方式,以及我对它们的反对意见:

  1. Define a new class, EditPersonViewModelDesign , that would mirror all the EditPersonViewModel properties, and use that as the design instance. 定义一个新类EditPersonViewModelDesign ,该类将镜像所有EditPersonViewModel属性,并将其用作设计实例。

     public class EditPersonViewModelDesign { public Person Person { get; set; } public ICommand SavePersonCommand { get; set; } } 
     <StackPanel d:DataContext="{d:DesignInstance vm:EditPersonViewModelDesign}"> <TextBox Text="{Binding Person.Name}" /> <Button Command="{Binding SavePersonCommand}" /> </StackPanel> 

    While that does not require an undue amount of code, the fact that this class will still be left in the library at runtime unless I ask people to complicate the build (whether they add a project with only these classes, or they add build variables) does not sit altogether well with me. 虽然不需要太多代码,但除非我要求人们使构建复杂化(无论他们是否仅添加这些类的项目,还是添加构建变量),否则此类仍会在运行时保留在库中,这一事实与我完全不合身 Also, it is easier for the Design and the View model classes to drift apart. 而且,Design和View模型类更容易分开。

  2. Refine the data context of the inner element and affect a new design instance to it, eg: 完善内部元素的数据上下文并对其影响新的设计实例,例如:

     <StackPanel d:DataContext="{d:DesignInstance vm:EditPersonViewModel}"> <TextBox DataContext="{Binding Person}" d:DataContext="{d:DesignInstance m:Person}" Text="{Binding Name}" /> <Button Command="{Binding SavePersonCommand}" /> </StackPanel> 

    While that solution does not require creating a new type, the added XAML code feels pretty invasive to me. 尽管该解决方案不需要创建新的类型,但是添加的XAML代码对我来说非常具有侵入性。

I don't think that there actually is a satisfying solution here, as the only true 'not-workaround' would be a native support of IntelliSense for dynamic binding targets (ie call GetDynamicMemberNames on the DynamicMetaObject returned by GetMetaObject() of the design instance of Model<T> . So, I would recommend a feature request , first of all. 我认为这里实际上没有令人满意的解决方案,因为唯一真正的“非解决方法”是对动态绑定目标(即在设计实例的GetMetaObject()返回的DynamicMetaObject上调用GetDynamicMemberNames对IntelliSense的本机支持。的Model<T>所以,我建议一个特征请求 ,首先。

If I were your customer, I would not spend the effort of defining design time bindings everywhere just for IntelliSense support. 如果我是您的客户,我将不会花很多精力在所有地方都为IntelliSense支持而定义设计时间绑定。 It requires more thinking to specify the correct bindings than to remember or look up and type the property names. 与记住或查找并键入属性名称相比,需要更多的思考来指定正确的绑定。

Here is one idea, which might work. 这是一个想法,可能可行。 I haven't tested it, of course, but with some research it might get you there. 当然,我还没有测试过,但是经过一些研究,它可能会带您到那里。 You seem to be knowing, what you're doing: 您似乎知道自己在做什么:

Have a look at the IsInDesignTool property of the static DesignerProperties class in System.ComponentModel : 看一下System.ComponentModel静态DesignerProperties类的IsInDesignTool属性:

DesignerProperties.IsInDesignTool

A kind of if DesignMode do this, else do that approach which can be implemented in the ViewModels is presented here . A类if DesignMode do this, else do that的办法,可以在的ViewModels实施,提出在这里 This could be an approach to return the inner model (of type T), instead of the wrapped model (Model). 这可能是返回内部模型 (类型T)而不是包装模型(模型)的方法。 Not sure whether it would get you anywhere , but it might be worth it to think it through. 不知道它是否可以带您到任何地方,但是仔细考虑可能值得。 It's an interesting feature to know about, anyway... 无论如何,这是一个有趣的功能……

Last idea: Improve the user experience by shipping code snippets and think of an intuitive way to distinguish the design time binding and the runtime binding. 最后一个想法:通过发布代码段来改善用户体验,并想到一种区分设计时间绑定和运行时绑定的直观方法。 Maybe something like: 也许像:

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; }
}

Code snippet which creates 创建的代码段

d:Text="{Binding DesignModel.Name}" Text="{Binding Model.Name}"

Don't know, how powerful VS code snippets are, because I'm using ReSharper, but with ReSharper, you would make the DP of the control a variable $ControlProp$ , the property name a variable $PropName$ . 不知道,VS代码段的功能多么强大,因为我正在使用ReSharper,但是使用ReSharper,您会将控件的DP设置为变量$ControlProp$ ,将属性名称$PropName$变量。 Then IntelliSense would work on the design time binding and would automatically copy the property name to the second binding, if you hit enter. 然后,如果您按Enter键,则IntelliSense将在设计时绑定上起作用,并将属性名称自动复制到第二个绑定。

You would enter some shortcut pbind , then Text , Enter, N , which would fire IntelliSense, select Name , Enter. 您将输入一些快捷方式pbind ,然后输入Text ,Enter和N ,这将触发IntelliSense,选择Name ,Enter。 Done. 完成。 Would be easy, at least. 至少会很容易。

Bottomline: I don't have a plug and play answer to your question, but my points might be good for some inspiration... At least I hope so. 底线:对于您的问题,我没有即插即用的答案,但我的观点可能会有所启发...至少我希望如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在自定义设计器中使用Visual Studio资源选择器对话框 - How to Use Visual Studio Resource Selector Dialog in Custom Designer 如何在Visual Studio 2010中提升XAML设计器? - How to boost up XAML designer in visual studio 2010? 在Visual Studio 2010 Designer中使用自定义控件 - Using custom controls in Visual Studio 2010 Designer Visual Studio Designer表单中ToolStrip的自定义ToolStripButton - Custom ToolStripButton for ToolStrip in Visual Studio Designer form 显示控件列表的 Visual Studio 窗体设计器 - Visual Studio Form Designer Showing List of Controls 如何使Visual Studio外接程序在设计器中设置控件的Visible属性 - How to make a Visual Studio addin set a control's Visible property in the designer 如何在Visual Studio设计器的属性部分的多行文本框中添加换行符 - How to add a line break in a multi line textbox in Visual Studio designer's property section Visual Studio Designer如何自动创建关联 - Visual Studio designer how to automatically create associations 如何为Visual Studio构建/扩展设计器 - How to build/extend a designer for Visual Studio Visual Studio会在设计器文件中继续插入荒谬的默认属性值 - Visual Studio keeps inserting absurd default property value in designer file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM