2012-03-12 8 views
2

テキストボックスの値が変更されたときに[追加]ボタンを使用できるようにするために実装します。双方向バインディングの問題 - PropertyChanged&CanExecuteChanged

私はViewModelにしてテキストボックスをバインド:

<TextBox Name="nameTbx" Text="{Binding Path=NewNode.Name, Mode=TwoWay}" /> 

マイボタン:私の背後にあるXAMLコードで

<Button Content="Add" Command="{Binding Path=AddNewNodeProperty}"/> 

は私のViewModelにのDataContextを設定します。 ViewModelには、次のようになります。私はここ_addNewNodeProperty

this._addNewNodeProperty = new AddNode(this); 

を初期化するコンストラクタで

/* code*/ 

private Node _newNode = new Node(); 
public Node NewNode 
{ 
    get 
    { 
     return _newNode; 
    } 
    set 
    { 
     _newNode = value; 
     OnPropertyChanged("NewNode"); 
    } 
} 

private AddNode _addNewNodeProperty; 
    public AddNode AddNewNodeProperty 
    { 
     get 
     { 
      return _addNewNodeProperty; 
     } 
    } 

は、私た。AddNodeクラスです:

public class AddNode : ICommand 
{ 
    private ServiceMapViewModel viewModel; 

    public AddNode(ServiceMapViewModel viewModel) 
    { 
     this.viewModel = viewModel; 
     this.viewModel.PropertyChanged += (s, e) => 
     { 
      if (CanExecuteChanged != null) 
      { 
       CanExecuteChanged(this, new EventArgs()); 
      } 
     }; 
    } 

    public bool CanExecute(object parameter) 
    { 
     bool b = !string.IsNullOrWhiteSpace(this.viewModel.NewNode.Name); 

     return b; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     this.viewModel.AddNewNode(); 
    } 
} 

そして最後に、私のNodeクラス:

public class Node 
{ 
    public string Name { get; set; } 

    public bool? IsChecked { get; set; } 

    public Group Group { get; set; } 

    public Category Category { get; set; } 

    public string Metadata { get; set; } 

    public List<string> Children = new List<string>(); 

    public List<string> Parents = new List<string>(); 
} 

プロ私のテキストボックスのテキストを変更すると、NewNodeは値を取得していますが、それは設定されているはずです。

Tnx in advanced!

EDIT は私が何かを追加してみましょう:

私はまた、画面上のデータグリッドを持っており、選択項目が変更されたとき、私の追加butomが利用可能になります。

選択項目:

<DataGrid Name="nodeDataGrid" ItemsSource="{Binding Path=MyServiceMap.Nodes}" 
     Background="Silver" Margin="0,34,10,10" IsReadOnly="True" SelectedItem="{Binding Path=SelectedNode}" > 

とVM:

private Node _selectedNode = new Node(); 
    public Node SelectedNode 
    { 
     get 
     { 
      return _selectedNode; 
     } 
     set 
     { 
      _selectedNode = value; 
      OnPropertyChanged("SelectedNode"); 
     } 
    } 

答えて

1

あなたのTextBoxのは、あなたのNodeオブジェクトのNameプロパティにバインドされています。 Nameプロパティは、変更されたときにPropertyChangedイベントを発生させません。変更されたときには、NewNodeプロパティ全体がイベントを発生させます。編集が提供する

提案

一つのアプローチは、としてmtaboyINotifyPropertyChangedインタフェースを実装し、提案し、NodeViewModelクラスを作成することです。 ViewModel上でユーザーに公開するプロパティを作成します。モデル(つまり、Nodeクラス)とビュー(ユーザーに表示されるUI)の間にViewModelがあると考えることができます。

ICommand論理を独自のクラスにカプセル化することをお勧めします。私がよく使うのはRelayCommandクラスで、MSDNのJosh SmithのMVVM articleにあります。そのクラスを使用する場合は、ViewModelクラスのプロパティまたはプライベートメソッドのいずれかを定義して、ユーザーが追加できるかどうかを返します。

private bool CanAddNewNode() 
{ 
    return !String.IsNullOrWhitespace(Name); 
} 

あなたRelayCommandをインスタンス化する場合たとえば、あなたは上記のそのメソッドを指し、2番目のパラメータのラムダを渡すことができます。

var saveCommand = new RelayCommand(param => SaveMethod(), param => CanAddNewNode()); 

あなたがRelayCommandオブジェクトを返しますあなたのViewModelからICommandプロパティを公開します。

うまくいけば、それはあなたを始めます。

+0

何をお勧めしますか? :) – Bip

+0

いくつかの具体的な提案を提供するために私の答えを更新しました。 –

1

問題は、私は私のテキストボックスのテキストを変更する場合、NewNodeが私のために 値を取得しているが、それがになっていることです設定します。

Nodeクラスの場合は、INotifyPropertyChangedインターフェイスもサポートする必要があります。

また、各文字の更新中にproeprtyを同期させたい場合は、UpdateSourceTriggerを試してみてください。さもなければ、プロパティはLostFocusイベントで更新されます。

<TextBox Name="nameTbx" 
     Text="{Binding Path=NewNode.Name, 
         Mode=TwoWay, 
         UpdateSourceTrigger=PropertyChanged}" /> 
+0

それが機能していない... – Bip

+0

申し訳ありませんが終了したばかりの答え – sll

+0

を見るため

public class Node:INotifyPropertyChanged { #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion string _name ; public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } } ..... 

をINotifyPropertyChangedのImpliment必要があります私はWCFを介して.XMLからデータを読み込んでいます。私が実装すると、.XMLからデータを取得できませんでしたINotifyPropertyChanged。 – Bip

1

あなたのノードクラスは、より多くの情報は私がすることを試みたMVVM Pattern

+0

私はそれを試みましたが、私はWCFを介して.XMLからデータを読み込みました.IntifyPropertyChangedを実装すると、.XMLからデータを取得できませんでした。 – Bip

+0

mvvmのimpliment obseverpatternについては、INotifyPropertyChangedを暗黙に実装する必要があります。記事http://www.codeproject.com/Articles/87510/WCF-by-Example-Introduction –

+0

文字通り 'クラスNode:INotifyPropertyChanged' - これは継承ではなく、これはインターフェイスの実装です – sll

関連する問題