在属性更改

时间:2015-06-08 10:59:59

标签: c# .net wpf mvvm

我正在开发一个WPF应用程序,我有一个文本框(双向)绑定到我的视图模型中的属性。

我试图阻止用户在此文本框中输入超过100个字符(这是数据库将存储的最大值),所以我写了这个。

public abstract class AppBaseViewModel : ViewModelBase
{
    private String _text;

    public String Text
    {
        get { return _text; }
        set
        {
            _text = CheckTextLength(value, _text);
            OnPropertyChanged("Text");
        }
    }

 private string CheckTextLength(string value, string text)
    {
        if (value.Length < 100)
        {
            return value;
        }
        else
        {
            return text; 
        }
    }
}  

所有这些代码似乎都是将前100个字符保存到字段中,但它仍然允许用户继续输入超过100个字符...我猜这是因为字段值没有被传递回文本框。

我不明白为什么这不起作用,因为我在不同的应用程序中使用MVVM Light的RaisePropertyChange()做了类似的事情。

值得注意的是,我无法访问文本框的设计器,因此无法将.Net文本框属性设置为最大长度。

编辑:为了澄清我无法查看或编辑xaml,因为有些人建议我没有访问XAML文件(我知道,这是愚蠢的)。我们使用的所有绑定默认为双向

4 个答案:

答案 0 :(得分:0)

您是否尝试使用TextBox.MaxLength?

<TextBox MaxLength="100"/>

Gets or sets the maximum number of characters that can be manually entered into the text box.

如果无法访问XAML,最终可以访问XAML,而不是解析和验证数组的长度,并在此处使用子字符串。至少我会为这个简单的问题做些什么,或者与设计师讨论添加这一小段代码。

更新1

    public static T GetChildOfType<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj == null) return null;

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            var child = VisualTreeHelper.GetChild(depObj, i);

            var result = (child as T) ?? GetChildOfType<T>(child);
            if (result != null) return result;
        }
        return null;
    }

去找那个孩子并设置它的MaxLength。这只是对View的一点修改,因此它不会影响MVVM模式。

答案 1 :(得分:0)

行。我完全不确定我为此感到骄傲,但我将它作为另一种选择。

您可以通过将通用样式应用于所有TextBox 来更改TextBox的Text属性的UpdateSourceTrigger。这只是在非常奇怪的安排中实用,但问题本身有点不寻常。

XAML代码隐藏:

//I'm using MVVM Light here - you need to be able to find an instance
//of your AppBaseViewModel somehow.
private ViewModelLocator _locator;

//View codebehind constructor, may need to change names as appropriate
public AppBaseView()
{
    InitializeComponent();

    //MVVM Light again
    _locator = new ViewModelLocator();

    //Create the binding
    Binding binding = new Binding();

    //Source = The instance of your ViewModel
    binding.Source = _locator.AppBaseViewModel ;
    binding.Path = new PropertyPath("Text");
    binding.Mode = BindingMode.TwoWay;
    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

    //Create a Style with no Key - this will apply to *all* TextBoxes
    //without their own explicit Style set.
    Style style = new Style(typeof(TextBox));
    style.Setters.Add(new Setter(TextBox.TextProperty, binding));

    //Add the Style to the XAML's Resources:
    Resources.Add(typeof(TextBox), style);
}

答案 2 :(得分:0)

如果该视图当前正在尝试更改该属性,则该视图不会收听PropertyChanged通知。

唯一想到的是当您检测到不符合约束时启动额外延迟的PropertyChanged通知...

private string CheckTextLength(string value, string text)
{
    if (value.Length < 100)
    {
        return value;
    }
    else
    {
        MyDispatcher.BeginInvoke(new Action(() =>
            OnPropertyChanged("Text")), 
            DispatcherPriority.Loaded);
        return text; 
    }
}

无法尝试代码,如果它没有建立起来,那就很抱歉。例如,MyDispatcher可能是您的Application.Current.Dispatcher

答案 3 :(得分:0)

xaml视图/绑定仅在文本框失去焦点时更新。如果输入的文本是&lt; 100,则设置该值,否则设置_text。这意味着最初_text没有值,因此在if语句为false时将设置null。我还建议你使用RaisePropertyChanged();当在属性中使用时,不需要任何参数。