2012-07-17 39 views
1

我想了解如何正確使用MVVM和數據綁定時,我們正在處理許多屬性。如何調用數據綁定的一般方法?

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="463" Text="{Binding OriginalText, UpdateSourceTrigger=PropertyChanged}" /> 
    <Label Height="28" HorizontalAlignment="Left" Margin="12,242,0,0" Name="label1" VerticalAlignment="Top" Width="463" Content="{Binding ModifiedText}"/> 
    <CheckBox Content="Upper" Height="16" HorizontalAlignment="Left" Margin="12,41,0,0" Name="checkBox1" VerticalAlignment="Top" /> 
    <CheckBox Content="Underline" Height="16" HorizontalAlignment="Left" Margin="12,63,0,0" Name="checkBox2" VerticalAlignment="Top" /> 
    <CheckBox Content="Bold" Height="16" HorizontalAlignment="Left" Margin="12,85,0,0" Name="checkBox3" VerticalAlignment="Top" /> 
    <CheckBox Content="Shadow" Height="16" HorizontalAlignment="Left" Margin="12,107,0,0" Name="checkBox4" VerticalAlignment="Top" /> 
    <CheckBox Content="Red" Height="16" HorizontalAlignment="Left" Margin="12,129,0,0" Name="checkBox5" VerticalAlignment="Top" /> 
    <CheckBox Content="Scary" Height="16" HorizontalAlignment="Left" Margin="12,151,0,0" Name="checkBox6" VerticalAlignment="Top" /> 
    <CheckBox Content="Remove first letter" Height="16" HorizontalAlignment="Left" Margin="12,173,0,0" Name="checkBox7" VerticalAlignment="Top" /> 
    <CheckBox Content="Remove last letter" Height="16" HorizontalAlignment="Left" Margin="12,195,0,0" Name="checkBox8" VerticalAlignment="Top" /> 
</Grid> 

我有一個OriginalText文本框和一個ModifiedText標籤。當我選中一個框時,我想直接應用修改而不必點擊一個按鈕。我應該怎麼做?

在我的ViewModel中,我創建了綁定到XAML CheckBox的所有屬性。

private string _originalText = string.Empty; 
    public string OriginalText 
    { 
     get { return _originalText; } 
     set 
     { 
      _originalText = value; 
      NotifyPropertyChanged("OriginalText"); 
     } 
    } 

    private string _modifiedText; 
    public string ModifiedText 
    { 
     get { return _originalText; } 
     set 
     { 
      _originalText = value; 
      NotifyPropertyChanged("ModifiedText"); 
     } 
    } 

    private bool upper; 
    public bool Upper 
    { 
     get { return upper; } 
     set 
     { 
      upper = value; 
      NotifyPropertyChanged("Upper"); 
      // Should I notify something else here or call a refresh method? 
     } 
    } 

    private bool removeFirstLetter; 
    public bool RemoveFirstLetter 
    { 
     get { return removeFirstLetter; } 
     set 
     { 
      removeFirstLetter = value; 
      NotifyPropertyChanged("RemoveFirstLetter"); 
      // Should I notify something else here or call a refresh method? 
     } 
    } 

    // ... 

然後我在這個時候在同一個ViewModel類中創建了一個Work方法。我將在稍後將此方法應用到業務中。

private void Work() 
{ 
    string result = _originalText; 
    if (Upper) 
     result = result.ToUpper(); 
    if (removeFirstLetter) 
     result = result.Substring(1, result.Length); 
    // if ... 
    ModifiedText = result; 
} 

我的問題是什麼時候,我應該在哪裏調用工作方法?我應該在每個二傳手還是吸手?我不喜歡這個想法。我做錯了什麼...

謝謝。

回答

1

在您的具體情況下,您應該使用INotifyPropertyChanged接口創建布爾屬性。現在將此屬性綁定到您的「IsChecked」複選框屬性。通過在setter中調用你的Work()方法,每當複選框被勾選時,setter將每次觸發。

0

您的問題的答案很簡單:使用Commands

命令是MVVM的方式來實現綁定到您的ViewModel中的方法。 Commands的實現遵循一個非常標準的模式。你會發現大量的信息在互聯網上這裏只是一個小品:在您的視圖模型實現

命令必須ICommand類型和每一個命令與在代碼中一個負責執行實際的方法,一起走方法,另一個用於檢查當前是否可以執行。

這些方法必須分別命名爲CanExecuteExecute。通常情況下,通過一個稱爲DelegateCommand的小型幫助類來幫助使用幾個命令,該類爲前面提到的方法提供委託。

把這個類,因爲它是沒有任何修改:

public class DelegateCommand<T> : ICommand { 

    private Predicate<T> canExecute; 
    private Action<T> execute; 

    public event EventHandler CanExecuteChanged; 

    public DelegateCommand (Predicate<T> canExecute, Action<T> execute) { 

     this.canExecute = canExecute; 
     this.execute = execute; 
    } 

    public bool CanExecute (object param) { 

     return canExecute((T)param); 
    } 

    public void Execute (object param) { 


     execute((T)param); 
    } 

    public void CanExecuteChangedRaised() { 

     CanExecuteChanged(this, new EventArgs()); 
    } 
} 

,您的命令聲明是DelegateCommand型的,而不是ICommand類型。請看下面的例子來說明,你會得到的想法:

Supose你有一個方法foo()在你的ViewModel要與一個點擊一個按鈕來調用:

class ViewModel { 

    // ... 

    public DelegateCommand<object> FooCommand { get; set; } 

    public ViewModel() { 

     FooCommand = new DelegateCommand<object>(CanExecuteFooCommand, ExecuteFooCommand); 
    } 

    public bool CanExecuteFooCommand (object param) { 

     return true; 
    } 

    public void ExecuteFooCommand (object param) { 

     foo(); 
    } 

    // ... 
} 

假如你有設置您的視圖模型作爲對照DataContext通過它DataContext財產唯一剩下要做的就是綁定FooCommand您的按鈕是這樣的:

這就是它!

附錄(指評論):

爲了有一定的操作發生的位置,而無需實際敲擊按鈕,您就只需要跟蹤您的視圖模型的UI任何變化,做出相應的反應 - 這就是MVVM是關於:跟蹤UI中的數據修改或處理它們,並將它們填充回UI。

要在文本框的文本改變作出反應,您的視圖模型創建相應的字符串屬性和跟蹤視圖中的新ioncoming值是否是當前的textBox文本不同:

private string _text; 

public string Text { 
    get { return _text; } 
    set {   
     // the text in the TextBox is about to change. 
     if (!_text.Equals(value)) 
     { 
     doSomething(); 
     } 

     _text = value; 
     FirePropertyChanged("Text"); 
    } 
} 

做同樣的你CheckBox你可以像上面描述的那樣應用ICommand,因爲CheckBox是從Button派生的,因此它提供了Command屬性。

+0

謝謝你的幫助。其實我知道我必須在我的按鈕上創建一個ICommand。我的按鈕做工作()和保存()結果。我的問題不是關於點擊按鈕,但我怎麼能調用我的工作()方法來預覽我的結果,而不用每次我的用戶檢查或取消選中選項或修改原始文本時保存命中。 – 2012-07-18 07:53:51

+0

@DranDane查看我的附錄。 – 2012-07-18 08:35:37

相關問題