我找到了INotifyPropertyChanged
的代码段但它显示的代码如下:
我会这样:
:第一个字母的大写字母+ ...
:第一个字母的下划线+小写字母+ ...
我怎样才能做到这一点?
修改:无需输入公共字段和私有字段
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property type</ToolTip>
<Default>string</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>Property name</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>notifyMethod</ID>
<ToolTip>name of method to raise PropertyChanged event</ToolTip>
<Default>NotifyPropertyChanged</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[private $type$ _$property$;
public $type$ $property$
{
get { return _$property$;}
set
{
if (value != _$property$)
{
_$property$ = value;
$notifyMethod$("$property$");
}
}
}
$end$]]>
</Code>
</Snippet>
答案 0 :(得分:12)
片段可以用xml编写,可以用于vs
中的任何语言<?xml version="1.0" encoding="utf-8"?>
<CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<Header>
<Title>Notify Property Changed Method</Title>
<Author>Akash</Author>
<Shortcut>npcm</Shortcut>
<Description>This method implements the OnPropertyChanged method and binds to the event handler</Description>
<SnippetTypes>
<SnippetType>SurroundsWith</SnippetType>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Code Language="CSharp">
<![CDATA[#region Notify Property Changed Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!=null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion]]>
</Code>
</Snippet>
</CodeSnippet>
这是自动生成notify属性更改方法的代码。您需要做的就是将它保存在一个文件中,文件/ VisulaStudio(YourVersion)/ Code Snippets / Visual C#/
中的扩展名为片段就是你准备好使用它......
现在,请观察代码片段中有快捷方式标记..此标记引用了在写入时应该在vs中使用的标记以激活代码段。
这是属性本身的代码:
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<Header>
<Title>Notifiable Property</Title>
<Author>Akash</Author>
<Shortcut>nprop</Shortcut>
<Description>Property With in Built Property Changed method implementation.</Description>
<SnippetTypes>
<SnippetType>SurroundsWith</SnippetType>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>Type</ID>
<Default>string</Default>
</Literal>
<Literal>
<ID>Property</ID>
<Default>PlaceHolder</Default>
</Literal>
</Declarations>
<Code Language="CSharp">
<![CDATA[private $Type$ _$Property$;
public $Type$ $Property$
{
get { return _$Property$; }
set {
if(value!=null || value != _$Property$) _$Property$ = value;
OnPropertyChanged("$Property$");
}
}]]>
</Code>
</Snippet>
</CodeSnippet>
在这个特定的片段中,您需要做的就是键入nprop并按Tab键,它会生成所需的代码..您只需要输入数据类型和名称..其余部分由片段本身处理。
虽然这是一个更好的解决方案并且大大提高了编码速度,但这适用于小型项目,只有viewmodelbase方法适用于大型项目。
答案 1 :(得分:7)
我不认为可以使用Visual Studio提供的本机代码段功能来完成此操作。
我个人使用Resharper使它成为可能。它可以把我写的代码变成
public string Name { get; set; }
到
private string _name;
public string Name
{
get { return _name; }
set
{
if(value == _name)
return;
_name = value;
OnPropertyChanged("Name");
}
}
它甚至为您生成OnPropertyChanged()
方法。
答案 2 :(得分:2)
不幸的是,使用代码段无法做到这一点。
您需要转换$property$
或其他一些文字。即使您将属性名称拆分为2个部分(首字母和其余部分),您也必须使字母大写(或者反之 - 小写)。
片段仅提供非常有限数量的转换函数 - 对于C#而言只有3个,而不是其中一个可以提供所需的结果。请参阅MSDN上的Code Snippet Functions。对于截至2013年的所有Visual Studio版本都是如此。
答案 3 :(得分:1)
我会给你一个你不想听到的答案:你根本不应该这样做。您的模型应具有(完整或自动)属性,然后您的ViewModel属性应该只有一个getter和一个返回_model.MyProperty
的setter。
此外,您可能希望调查CallerMemberName
以摆脱那个讨厌的魔法字符串。如果你想要我,我会发布一些例子。
例如,我有一个DealsUser
模型类(注意内部逻辑如何生成电子邮件地址,如果它从未明确设置,则在这里完成):
public class DealsUser : IDealsUser
{
public DealsUser() : this("GUEST")
{
}
public DealsUser(string username)
{
this.Username = username;
this.IsAdministrator = false;
this.IsPlanModerator = false;
this.IsPlanner = false;
}
public string Username { get; set; }
public bool IsAdministrator { get; set; }
public bool IsPlanModerator { get; set; }
public bool IsPlanner { get; set; }
private string _emailAddress;
public string EmailAddress
{
get
{
return _emailAddress ?? string.Format(
"{0}@mycompany.co.za", this.Username);
}
set
{
_emailAddress = value;
}
}
public override string ToString()
{
return this.Username;
}
我有一个BaseViewModel
类,其中包含以下事件和受保护的方法(请注意我们如何使用CallerMemberName
来消除魔术字符串):
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
protected bool SetProperty<T>(ref T storage, T value,
[CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value))
{
return false;
}
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected bool SetModelProperty<T>(T storage, T value, Action setter,
[CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value))
{
return false;
}
setter();
this.OnPropertyChanged(propertyName);
return true;
}
#endregion
然后我从BaseViewModel
继承,我依赖将模型注入我的构造函数中,并尝试让我的ViewModel 尽可能精简。请注意,我必须使用SetModelProperty
而不是SetProperty
,因为您无法将属性(例如_dealsUser.Username
)作为参考变量传递给lamba函数。另请注意,IsPlanner
和IsPlanModerator
包含额外的逻辑,可在更改时更新相关的通知属性:
public class DealsUserVM : BaseViewModel
{
private readonly IDealsUser _dealsUser;
public DealsUserVM()
: this(new DealsUser())
{
// Empty ctor
}
public DealsUserVM(IDealsUser dealsUser)
{
_dealsUser = dealsUser;
}
public IDealsUser Model
{
get
{
return _dealsUser;
}
}
public string Username
{
get { return _dealsUser.Username; }
set
{
SetModelProperty(_dealsUser.Username, value,
() => { _dealsUser.Username = value; });
}
}
public bool IsAdministrator
{
get { return _dealsUser.IsAdministrator; }
set
{
SetModelProperty(_dealsUser.IsAdministrator, value,
() => { _dealsUser.IsAdministrator = value; });
}
}
public bool IsPlanModerator
{
get { return _dealsUser.IsPlanModerator; }
set
{
// If IsPlanModerator has changed (and was updated as a result)
if (SetModelProperty(_dealsUser.IsPlanModerator, value,
() => { _dealsUser.IsPlanModerator = value; }))
{
// If IsPlanModerator is now TRUE
if (value)
{
this.IsPlanner = true;
}
}
}
}
public bool IsPlanner
{
get { return _dealsUser.IsPlanner; }
set
{
// If IsPlanner has changed (and was updated as a result)
if (SetModelProperty(_dealsUser.IsPlanner, value,
() => { _dealsUser.IsPlanner = value; }))
{
// If IsPlanner is now FALSE
if (!value)
{
this.IsPlanModerator = false;
}
}
}
}
public string EmailAddress
{
get { return _dealsUser.EmailAddress; }
set
{
SetModelProperty(_dealsUser.EmailAddress, value,
() => { _dealsUser.EmailAddress = value; });
}
}
public override string ToString()
{
return _dealsUser.ToString();
}
}
希望这会有所帮助: - )
答案 4 :(得分:0)
令我惊讶的是,还没有提出以下建议。我拿了你的初始片段(来自原作者的页面)并进行了以下修改。您应该能够将其复制并粘贴到您自己的代码段文件中。
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>propn</Title>
<Shortcut>propn</Shortcut>
<Description>Code snippet for property and backing field in class implementing INotifyPropertyChanged</Description>
<Author>Brian Schroer, Modified by RLH</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property Type</ToolTip>
<Default>int</Default>
</Literal>
<Literal>
<ID>variable</ID>
<ToolTip>Underlying Variable</ToolTip>
<Default>_myProperty</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>Property name</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>notifyMethod</ID>
<ToolTip>name of method to raise PropertyChanged event</ToolTip>
<Default>NotifyPropertyChanged</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[private $type$ $variable$;
public $type$ $property$
{
get { return $variable$;}
set
{
if (value != $variable$)
{
$variable$ = value;
PropertyChanged(this, new PropertyChangedEventArgs("$property$"));
}
}
}
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
改变了什么
首先,我添加了一个新的文字variable
。这将创建一个新的可更新项目,您可以在该代码段中对其进行制表。变量名默认为_propertyName
,如您所见,它是一个小写名称。请注意,与原始代码段不同,下划线在PropertyName
字面值之前被硬编码。在我的代码中,我从属性名称中拆分了变量名。
我选择不对我的代码段中的下划线进行硬编码,这样如果其他人使用此代码,他们可以自由选择不同风格的变量名称。但是,作为默认设置,我使用下划线提示。
如果要强制使用下划线,请将默认variable
值更改为propertyName
。然后,在引用variable
的任何地方,将_
字符放在引用之前。