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>

OriginalTextTextBoxとModifiedTextLabelがあります。チェックボックスをオンにすると、ボタンをクリックせずに直接変更を適用したいと思います。どうすればいいですか?

ViewModelで、XAMLチェックボックスにバインドされるすべてのプロパティを作成しました。

    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; 
}

私の質問は、いつ、どこで作業メソッドを呼び出すべきかということです。各セッターまたはゲッターで呼び出す必要がありますか?私はその考えが好きではありません。私は何か間違ったことをします...

ありがとうございました。

4

2 に答える 2

1

特定のケースでは、INotifyPropertyChanged インターフェイスを使用して Boolean プロパティを作成する必要があります。このプロパティを "IsChecked" チェック ボックス プロパティにバインドします。セッター内で Work() メソッドを呼び出すことにより、チェックボックスが「チェックされる」たびに、セッターが毎回トリガーされます。

于 2012-07-18T13:54:56.113 に答える
0

あなたの質問への答えは非常に簡単です: を使用してくださいCommands

コマンドは、ViewModel 内のメソッドへのバインドを実現するための MVVM の方法です。コマンドの実装は、非常に標準的なパターンに従います。インターネット上にはたくさんの情報がありますが、ここにあるのは簡単なスケッチです。

ViewModel に実装されたコマンドは型ICommandである必要があり、すべての Command はコード内のメソッドに付随する必要があり、1 つは実際のメソッドの実行を担当し、もう 1 つは実行が現在可能かどうかをチェックします。

これらのメソッドには、それぞれ名前CanExecuteを付ける必要がありExecuteます。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());
    }
}

次に、 Command 宣言は typeDelegateCommandではなく typeICommandです。次の例を見て説明すると、アイデアが得られます。

ボタンをクリックして呼び出したい ViewModel にメソッド foo() があるとします。

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();
    }

    // ...
}

ViewModel をそのプロパティをDataContext介してコントロールとして設定したと仮定すると、あとは次のようにボタンにバインドするだけです。DataContextFooCommand

それでおしまい!

付録 (コメント参照):

ボタンを実際に押さずにアクションを実行するには、ViewModel を使用して UI の変更を追跡し、それに応じて反応する必要があります。それが MVVM の目的です。 UI に戻ります。

TextBox Text の変更に対応するには、ViewModel で対応する文字列プロパティを作成し、View からの新しい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 プロパティを提供しているためです。

于 2012-07-17T16:11:38.950 に答える