使用INotifyPropertyChanged的代码片段

时间:2013-10-22 09:48:36

标签: c# visual-studio inotifypropertychanged code-snippets

我找到了INotifyPropertyChanged

的代码段

但它显示的代码如下:

INotifyPropertyChanged

我会这样:

    公共
  1. :第一个字母的大写字母+ ...

  2. 私人的
  3. :第一个字母的下划线+小写字母+ ...

  4. 我怎样才能做到这一点?

    修改:无需输入公共字段和私有字段

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

5 个答案:

答案 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函数。另请注意,IsPlannerIsPlanModerator包含额外的逻辑,可在更改时更新相关的通知属性:

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的任何地方,将_字符放在引用之前。