在MVVM中实现textbox lostfocus事件

时间:2014-10-14 06:18:57

标签: c# wpf xaml mvvm

我想完成一项简单的任务。 需要实现textbox lostfocus,当用户输入数据时,只要一个字段被填充并且他到达下一个字段,它就应该在前一个字段上激活验证功能。 另外,我正在使用MVVM模式。

所以我有这个课

public class data : INotifyPropertyChanged
{

    public string name;
    public string Name
    {
        get
        {
            return name;
        }

        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }
    public string firstname;
    public string FirstName
    {
        get
        {
            return firstname;
        }

        set
        {
            firstname = value;
            OnPropertyChanged("FirstName");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            // Raise the PropertyChanged event
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
} 

在Viewmodel中我得到了这个

data1 = new data() { name = "Eddie Vedder", firstname = "Eddie" }; //this line in initialization 
public data _data1;
public data data1
{
    get { return _data1; }
    set 
    {

        _data1 = value;
        ValidateThis();
        NotifyPropertyChanged(new PropertyChangedEventArgs("data1"));
    }
}

在Xaml中:

<StackPanel Orientation="Horizontal" >
    <Label Width="90" Content="Name" Height="28" HorizontalAlignment="Left" Name="lblName" VerticalAlignment="Top" />
    <TextBox Text="{Binding Path=data1.name, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"   MaxLength="40" TabIndex="2" Height="25" Margin="0,3,0,0" HorizontalAlignment="Left" Name="txtName" VerticalAlignment="Top" Width="200" />
</StackPanel>
<StackPanel Orientation="Horizontal" >
    <Label Width="90" Content="First Name" Height="28" HorizontalAlignment="Left" Name="lblFirstName" VerticalAlignment="Top" />
    <TextBox Text="{Binding  Path=data1.firstname, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" MaxLength="40" TabIndex="3" Name="txtFirstName" Height="25" Margin="0,3,0,0" VerticalAlignment="Top" Width="200" >
    </TextBox>
</StackPanel>

当我执行它时,我的绑定正在运行,因为它使用了默认名称Eddie Vedder。 当我调试它时,它不会输入类数据。

3 个答案:

答案 0 :(得分:13)

当你使用MVVM模式时,我假设你有一些绑定来查看模型属性,它看起来像: XAML:

<StackPanel>
    <!--Pay attention on UpdateSourceTrigger-->
    <TextBox Text="{Binding Text, UpdateSourceTrigger=LostFocus}" />
    <TextBox />
</StackPanel>

C#:

private string _text;
public string Text
{
    get { return _text; }
    set
    {
        _text = value;
        Validate(); // Desired validation
        OnPropertyChanged();
    }
}

如果将UpdateSourceTrigger设置为LostFocus,则在失去焦点时将触发属性更改。

答案 1 :(得分:3)

有一篇非常好的文章:MVVM WPF commands

首先创建一个类:DelegateCommand.cs

public class DelegateCommand<T> : System.Windows.Input.ICommand where T : class
{
    private readonly Predicate<T> _canExecute;
    private readonly Action<T> _execute;

    public DelegateCommand(Action<T> execute)
     : this(execute, null)
    {
    }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
            return true;

        return _canExecute((T)parameter);
    }

    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }

    public event EventHandler CanExecuteChanged;
    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
}

将委托添加到ViewModel中:

  private readonly DelegateCommand<string> _lostFocusCommand;

  public DelegateCommand<string> LostFocusCommand
  {
     get { return _lostFocusCommand; }
  }
  private string _input;
  public string Input
  {
     get { return _input; }
     set
     {
        _input = value;
     }
  }

并在ViewModel的构造函数中初始化它:

// _input will be the property you have with a binding to the textbox control in the view.
// in the canExecute part add the conditions you want to use to check if the lostfocus command will be raised
 _lostFocusCommand = new DelegateCommand<string>(
  (s) => { /* perform some action */
     MessageBox.Show("The lostfocuscommand works!");
  }, //Execute
  (s) => { return !string.IsNullOrEmpty(_input); } //CanExecute
  );

查看: 您需要添加以下命名空间

xmlns:b="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"  

和控件

<TextBox Grid.Column="0"
    Text="{Binding Input, UpdateSourceTrigger=PropertyChanged}">
    <b:Interaction.Triggers>
        <b:EventTrigger EventName="LostFocus">
            <b:InvokeCommandAction  Command="{Binding LostFocusCommand}" CommandParameter="{Binding Input}"/>
        </b:EventTrigger>
     </b:Interaction.Triggers>
  </TextBox>

答案 2 :(得分:0)

嗯这有点诀窍

public class Validate
{
    public static ErrorProperties ep = new ErrorProperties();
    public static bool ValidateThis(string PropertyName, string PropertyValue)
    {
        if (PropertyValue.Length > 10)
        {
            ep.ErrorPropertyName = PropertyName;
            return true;
        }
        return false;
    }
}

public class ErrorProperties
{
    public string ErrorPropertyName { get; set; }
    public string Error { get; set; }
}

public class data : INotifyPropertyChanged
{
    private ObservableCollection<ErrorProperties> _ErrorList = new ObservableCollection<ErrorProperties>();
    public ObservableCollection<ErrorProperties> ErrorList
    {
        get
        {
            return _ErrorList;
        }
        set
        {
            if (_ErrorList != value)
            {
                _ErrorList = value;
                OnPropertyChanged("ErrorList");
            }
        }
    }


    private string _Name;
    public string Name
    {
        get
        {
            return _Name;
        }
        set
        {
            if (_Name != value)
            {
                _Name = value;
                if (Validate.ValidateThis("Name", value))
                    ErrorList.Add(Validate.ep);
                OnPropertyChanged("Name");
            }
        }
    }


    private string _FirstName;
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            if (_FirstName != value)
            {
                _FirstName = value;
                if (Validate.ValidateThis("FirstName", value))
                    ErrorList.Add(Validate.ep);
                OnPropertyChanged("FirstName");

            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            // Raise the PropertyChanged event
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}