2010-08-31 71 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