wpf 在 MVVM 中实现文本框丢失焦点事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26353893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Implementing textbox lostfocus event in MVVM
提问by nostafict
I want to accomplish a simple task. Need to implement textbox lostfocus, As the user puts in data, as soon as one field is filled and he reaches on to the next, it should fire a validation function on the previous field. Also, I am using MVVM pattern.
我想完成一个简单的任务。需要实现 textbox lostfocus,当用户输入数据时,只要一个字段被填充并进入下一个字段,它应该在前一个字段上触发一个验证函数。另外,我正在使用 MVVM 模式。
So I have this class
所以我有这门课
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));
}
}
}
In the Viewmodel I got this
在 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"));
}
}
In Xaml:
在 Xml 中:
<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>
My binding is working as it shoes the default name Eddie Vedder when I execute it. When I debug it, it doesn't enter the class data.
我的绑定正在工作,因为它在我执行它时使用默认名称 Eddie Vedder。当我调试它时,它不输入类数据。
采纳答案by nostafict
Well this kinda did the trick
嗯,这有点成功了
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));
}
}
}
回答by Alexander.Ermolaev
As you use MVVM pattern I assume that you have some binding to view model property and it looks like: Xaml:
当您使用 MVVM 模式时,我假设您对视图模型属性有一些绑定,它看起来像:Xaml:
<StackPanel>
<!--Pay attention on UpdateSourceTrigger-->
<TextBox Text="{Binding Text, UpdateSourceTrigger=LostFocus}" />
<TextBox />
</StackPanel>
c#:
C#:
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
Validate(); // Desired validation
OnPropertyChanged();
}
}
If you set UpdateSourceTrigger to LostFocus, property changed will be fired when you lost focus.
如果将 UpdateSourceTrigger 设置为 LostFocus,则在失去焦点时会触发已更改的属性。
回答by blfuentes
There is a very nice article for this: MVVM WPF commands
有一篇非常好的文章:MVVM WPF commands
First create a class: the DelegateCommand.cs
首先创建一个类: 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);
}
}
Add the delegate into your ViewModel:
将委托添加到您的 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;
}
}
And initialize it in the constructor of the ViewModel:
并在 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
);
View: you need to add the following namespace
查看:需要添加如下命名空间
xmlns:b="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
And the control
和控制
<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>

