2010-08-31 85 views
1

我发现这个link关于类似的问题,除了我的文本框添加扭曲后需要一个格式化的值失去焦点后。WPF MVVM:TextBox需要的格式和按钮与IsDefault设置为True

<TextBox Text="{Binding Value}" MaxLength="{Binding MaskLength}"/> 
<Button Command="{Binding ExecuteCommand}" IsDefault="True"/> 

在用户在文本框中输入文本后,我想用用户定义的掩码格式化文本。例如,如果掩码是“00000”,则惯例将是右对齐和零填充。

123 => 0 A01 => 00A01
等等

,我快到的问题是,我应该只格式化文本一次,当用户有完成打字。目前,如果用户点击按钮,用户输入的值被推送到绑定并执行该命令。但是,如果他们按下“Enter”键,则该值不会被推送到绑定,并且命令仍然被执行。

我发现如何在用户按下回车键时推送绑定的唯一方法是更改​​文本框的绑定并指定UpdateSourceTrigger=PropertyChanged。这不能很好地工作,因为我实际上并不知道用户何时完成输入文本。

最简单的解决方案是在按下回车键时添加代码隐藏功能以设置按钮的焦点,但是我希望将焦点留在当前所在的文本框中。有没有人有办法解决这个问题,也许是附属物?

编辑:

这里是我的视图模型是如何格式化输入值的一个简单的例子。

public string Value 
{ 
    get 
    { 
     return mFieldValue; 
    } 
    set 
    { 
     SetValueAndRaisePropertyChange( 
      ref mFieldValue, 
      _ApplyFormat(value), 
      () => FieldValue); 
    } 
} 

这是我找到的最简单的黑客代码。我把它转换成了一个附属的房产,但它的气味仍然不太好。

private void _HandleTxtKeyDown(object sender, KeyEventArgs e) 
{ 
    if(e.Key == Key.Enter) 
    { 
     TextBox textBox = (TextBox)sender; 
     BindingExpression binding = textBox.GetBindingExpression(TextBox.TextProperty); 
     if(binding != null) 
     { 
      binding.UpdateSource(); 
     } 
    } 
} 

回答

0

如果我理解你的意图是正确的,那么事实上没有问题。

如果用户按下回车键/单击按钮,您只想掩盖输入?那么你已经找到的解决方案(UpdateSourceTrigger = PropertyChanged)将完全按照你的意图进行。虚拟机中的属性在您输入时更新。如果您使用PropertyChanged触发器,则按下输入/单击按钮后,该命令将不会执行。

默认的UpdateSourceTrigger是'LostFocus'。当然,如果你用鼠标点击按钮,而不是按下回车键,也会发生这种情况。

希望我能帮助你理解这个机制。

+0

将其设置为PropetyChanged不更新源但格式是正确的。假设我想将值'ab1'格式化为'00AB1'。如果在用户点击“a”时设置为PropertyChanged,则该值将变为“0000A”。现在用户点击'b',并且由于达到了最大长度而被忽略。 – 2010-08-31 15:51:50

+0

没有它没有。请参阅我的下一个答案,以查看完全有效的代码(已测试) – JanW 2010-08-31 16:19:14

0

你是不对的。如果该命令更新文本,则在输入时不会执行该命令,直到您按Enter键并单击该按钮。

的观点:

<Window x:Class="WpfApplication9.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <TextBox MaxLength="{Binding Path=MyLength}" 
       Text="{Binding Path=MyText, UpdateSourceTrigger=PropertyChanged}"/> 

     <Button Command="{Binding Path=MyCommand}" IsDefault="True">Enter</Button> 
    </StackPanel> 
</Window> 

视图模型,这是在构造函数指定为窗口的DataContext的:

public class MyViewModel : INotifyPropertyChanged 
{ 
    private string _myText = string.Empty; 
    private int _maxLength = 6; 
    private ICommand _myCommand; 

    public MyViewModel() 
    { 
     this._myCommand = new MySimpleCommand((obj) => { FormatMyText(); }); 
    } 

    private void FormatMyText() 
    { 
     this.MyText = this.MyText.PadLeft(this.MyLength, '0'); 
    } 

    public string MyText 
    { 
     get { return this._myText; } 
     set 
     { 
      this._myText = value; 
      PropertyChanged(this, new PropertyChangedEventArgs("MyText")); 
     } 
    } 

    public int MyLength 
    { 
     get { return this._maxLength; } 
     set { } 
    } 

    public ICommand MyCommand 
    { 
     get { return this._myCommand; } 
     set { } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public class MySimpleCommand : ICommand 
    { 
     private Action<object> _action; 

     public MySimpleCommand(Action<object> cmdAction) 
     { 
      this._action = cmdAction; 
     } 

     public bool CanExecute(object parameter) 
     { 
      return true; 
     } 

     public event EventHandler CanExecuteChanged; 

     public void Execute(object parameter) 
     { 
      _action(parameter); 
     } 

    } 
} 
+0

P.S:我建议您将断点放入MyText属性和FormatMyText()方法的setter中。 希望我能帮助你。 – JanW 2010-08-31 16:22:53

+0

是的,这有效。但是,我的命令没有执行格式化。 Value属性在更新绑定时进行格式设置(OnLostFocus [默认]或PropertyChanged)。 – 2010-08-31 16:29:52