一个方法应该从一个属性中“解雇”吗?

时间:2013-04-10 09:41:13

标签: mvvm properties

我的应用程序使用MVVM模式。我的TextBox绑定到我的ViewModel属性(类型字符串)。

TextBox的内容通过用户输入更改时,我想执行一些验证。

所以,目前,我的代码是

<TextBox Text="{Binding XmlContentAsString, UpdateSourceTrigger=PropertyChanged}" />

我的ViewModel有这个属性和字段:

        private string _xmlContentAsString;
        public string XmlContentAsString
        {
            get { return _xmlContentAsString; }
            set
            {
                if (_xmlContentAsString == value)
                    return;

                _xmlContentAsString = value;
                PerformValidiationLogic(value);//This is where I am unsure
            }
        }

现在,这可行但是,我不知道为什么,我不喜欢这个!在该属性中包含该方法的一些感觉“被黑客入侵”。

在使用MVVM模式时,有人可以告诉我这是否是正确的方法?

4 个答案:

答案 0 :(得分:1)

有不同类型的验证。 对于简化的验证字符串长度或允许的字符等,您可以使用DataAnnotations并将验证放在属性的属性中。你需要包括  使用System.ComponentModel.DataAnnotations;

然后例如将字符串保持为9个字符:

    [StringLength(9)]
    public string StringValue
    {
        get
        {
            return stringValue;
        }

        set
        {
            this.stringValue = value;
        }
    }

然后验证有点复杂,并且有效地强制执行您的业务逻辑。 关于如何做到这一点似乎有很多观点。理想情况下它应该属于模型,以便可以重用验证,但显然可以通过viewmodel调用。

我个人会偶尔在属性设置器中调用方法调用,对我而言,这就是有能力创建setter和getter的全部原因 - 否则除了自动属性之外没有其他任何东西。

但如果它很复杂或异步,那么你可以遇到问题。 我会非常小心地使用UpdateSourceTrigger = PropertyChanged,因为这意味着你将为每个角色解雇它。

答案 1 :(得分:1)

在您的示例中,您对值执行验证逻辑,但如果验证失败,那将是什么结果?通常,您希望通知用户验证失败。如果是这种情况,那么我建议使用IDataErrorInfo(例子可以在这里找到:

http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/)。

如果您计划在不通知用户的情况下覆盖该值,则可以接受在设置器中进行验证(但出于个人原因仍然不是粉丝)。

答案 2 :(得分:0)

在我看来,这是正确的方法。我会为你的ViewModel编写一个基类,它包含一个设置属性的方法,调用PropertyChanged并验证是否有一些验证规则附加到该属性。

例如:

public abstract class ValidableViewModel
{
    private List<ValidationRule> _validationRules;

    public ValidableViewModel()
    {
        _validationRules = new List<ValidationRule>();
    }

    protected virtual void SetValue<T, T2>(Expression<Func<T>> expression,
                                           ref T2 backend, T2 value)
    {
        if (EqualityComparer<T2>.Default.Equals(backend, value))
            return;

        backend = value;
        OnPropertyChanged(expression);

        Validate(expression.Name, value);
    }

    protected void Validate(string propertyName, object value)
    {
        foreach(var validationRule in _validationRules)
        {
            if(validationRule.PropertyName == propertyName)
                validationRule.Execute(value);
        }
    }
}

代码不完整,遗漏了很多。但它可能是一个开始; - )

答案 3 :(得分:0)

我个人并不建议在你的财产中加入如此多的逻辑。我会使用绑定到事件的命令,即文本框的lostfocus事件,并在那里执行验证。

我会用这样的东西:

 <TextBox Text="{Binding XmlContentAsString, UpdateSourceTrigger=PropertyChanged}">
        <interactivity:Interaction.Triggers>
            <interactivity:EventTrigger EventName="LostFocus">
                <interactivity:InvokeCommandAction Command="{Binding LostFocusCommand, Mode=OneWay}"/>
            </interactivity:EventTrigger>
        </interactivity:Interaction.Triggers>           
    </TextBox>

然后在您的视图模型中使用LostFocusCommand命令,并使用验证逻辑 我使用mvvm-light,可以为此提供更详细的示例。 (您需要在xaml顶部包含混合交互声明)