10

我找到了 INotifyPropertyChanged 的​​代码片段

但它显示了这样的代码:

INotifyPropertyChanged

我会有这个:

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

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

我怎样才能做到这一点?

编辑:无需键入公共和私有字段

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

5 回答 5

16

片段可以用 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>

这是自动生成通知属性更改方法的代码。您需要做的就是将其保存在单个文件中,扩展名为 Documents/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 方法适用于大型项目。

于 2015-06-18T15:40:46.730 回答
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()为您生成方法。

于 2013-11-13T15:40:29.987 回答
4

令我惊讶的是,没有提出以下建议。我获取了您的初始片段(来自原始作者的页面)并进行了以下修改。您应该能够将其复制并粘贴到您自己的代码片段文件中。

<?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被引用,将_字符放在引用之前。

于 2016-08-19T15:03:49.557 回答
2

不幸的是,使用代码片段这是不可能的。

您需要的内容必须转换$property$或其他一些文字。即使您将属性名称分成两部分(第一个字母和其余部分),您也必须将字母设为大写(或其他方式 - 小写)。

片段仅提供数量非常有限的转换函数——对于 C# 恰好 3 个,而且没有一个可以提供所需的结果。请参阅MSDN 上的代码片段函数。直到 2013 年的所有 Visual Studio 版本都是如此。

于 2013-11-10T06:06:08.523 回答
1

我会给你一个你不想听到的答案:你根本不需要这样做。您的模型应该具有(完整或自动)属性,然后您的 ViewModel 属性应该只有一个 getter 和一个返回的 setter _model.MyProperty

此外,您可能想研究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();
    }
}

希望这可以帮助 :-)

于 2013-11-13T17:14:36.540 回答