2017-08-21 6 views
1

XAMLのボタンをバインドして、データベース内のユーザーを更新しています。私はCanExecuteを利用して、ViewModel上のプロパティに変更が加えられた後にのみボタンを有効にしたいと考えています。CanExecuteを実装するために、およびEF6 Generatedクラスを使用してオブジェクトへの変更を認識する方法を教えてください。

私はCRUD操作を実行するために、Entity FrameworkとWCF Dataサービスを使用しています。私はRelayCommand(saveUser、someCommand)を結ぶとを持つことが可能であると考えてい

モデルクラス

public virtual DbSet<user> users { get; set; } 

    ... 

    namespace pk.Data 
    { 
     using System; 
     using System.Collections.Generic; 

     public partial class user 
     { 
      public user() 
      { 
       this.private_account = new HashSet<private_account>(); 
      } 

      public int id { get; set; } 
      public string username { get; set; } 
      public int superuser { get; set; } 
      public int enabled { get; set; } 

      public virtual ICollection<private_account> private_account { get; set; } 
     } 
    } 

WCFサービス

public class pkService 
{ 

    // getUsers() - 
    // Get all users from the database 
    [OperationContract] 
    public IEnumerable<user> getUsers() 
    { 
     using (var context = new pkEntities()) 
     { 
      // Needed in order to handle EF objects with Hashes 
      context.Configuration.ProxyCreationEnabled = false; 
      // Pull entity object fom DB 
      var results = context.users.ToList(); 
      // Detatch from Entity Model 
      results.ForEach(e => context.Entry(e).State = EntityState.Detached); 
      //Return detached object 
      return results; 
     } 
    } 

    // updateUser(user) - 
    // Update user in the DB 
    [OperationContract] 
    public void updateUser(user user){ 
     using (var context = new pkEntities()) 
     { 
      context.Configuration.ProxyCreationEnabled = false; 
      context.Entry(user).State = EntityState.Modified; 
      context.SaveChanges(); 
     } 
    } 
} 

ビューモデル#

public class HomeViewModel: ViewModelBase 
    { 
     // HomeViewModel() 
     // Class Constructor 
     public HomeViewModel() 
     { 
      this.RefreshUsers(); 
      userListClick = new RelayCommand<SelectionChangedEventArgs>(_userListClick); 
      saveUser = new RelayCommand(saveUser); 
     } 

     // users 
     // list of all users in the system 
     private IEnumerable<user> _users; 
     public IEnumerable<user> users 
     { 
      get { return this._users; } 
      set 
      { 
       this._users = value; 
       this.RaisePropertyChanged("users"); 
      } 

     } 

     // selected user 
     // currently selected user 
     private user _selectedUser; 
     public user selectedUser 
     { 
      get { return this._selectedUser; } 
      set 
      { 
       if (this._selectedUser != value) 
       { 
        this._selectedUser = value; 
        this.RaisePropertyChanged("selectedUser"); 
       } 
      } 
     } 

     // RefreshUsers() 
     // Method for retrieving users from DB 
     private void RefreshUsers() 
     { 
      this._pkServiceClient.getUsersCompleted += (s, e) => 
       { 
        this.users = e.Result; 
       }; 
      this._pkServiceClient.getUsersAsync(); 

     } 

     // serverListClick 
     public ICommand userListClick { get; private set; } 
     private void _userListClick(SelectionChangedEventArgs e) 
     { 
      ListView userList = (ListView)e.Source; 
      _selectedUser = (user)userList.SelectedItem; 
      this.setUserDetailsVisible(Visibility.Visible); 
      this.RaisePropertyChanged("selectedUser"); 
     }   

     public ICommand saveUser { get; private set; } 
     private void _saveUser() 
     { 
      this._pkServiceClient.updateUser(_selectedUser); 
     } 
    } 
} 

someCommandボタンを有効にした状態を制御するために、XAMLでバインドできる値を返します。

これを処理するためにEntity Generatedクラスを使用する方法を見つけることができないようです。どんな援助も素晴らしいだろう。

答えて

1

あなたが正しく理解していれば、saveUserコマンドに接続されているボタンをすぐに有効にしたいのですが、selectedUserに変更が加えられていますか?

私はRelayCommand(saveUser、someCommand)を結ぶとしていsomeCommand私はボタンの有効状態を制御するために、私のXAMLでと結合することができる値を返すことが可能であると考えています。

これはCompositeCommands(MSDN Documentation)で可能です。ここでは、メソッド "RegisterCommand"を呼び出して、CompositeCommandに接続されたButtonの動作に影響する2番目のコマンドを渡すことができます。したがって、登録されたButtonがCanExecute == falseを返した場合、ボタンは無効になります。

しかし、エンティティが正しい値を持っている場合、CanExecuteメソッドをRelayCommandに追加してそこにチェックを入れることもできます。例えば、CanExecute方法は、例えば、ユーザ名をチェックすることができ :

public HomeViewModel() 
{ 
    this.RefreshUsers(); 
    userListClick = new RelayCommand<SelectionChangedEventArgs>(_userListClick); 
    saveUser = new RelayCommand(saveUser, CanExecuteSaveUser); 
} 

private bool CanExecuteSaveUser() 
    { 
     if (selectedUser.username == "foo") 
     { 
      return true; 
     } 

     return false; 
    } 

私はあなたのモデルに直接接続しないでしょう。あなたのモデルは、UIの検証に必要なロジックで悩まされるべきではありません。したがって、ViewModelとWCF Serviceの間に追加のレイヤーを追加するのはおそらく、ユーザーのプロパティに直接加えられたすべての変更を処理できるUserViewModelの種類です。これらのプロパティを変更すると、RelayCommandのRaiseCanExecuteChangedメソッドがトリガされます。

私があなたに誤解を与えた場合は、この問題の詳細な説明をお送りください。

編集:あなたのコメントの後

、私はあなたがINotifyPropertyChangedのイベントを実装し、これらのイベントをサブスクライブすることができると思います。そのためには、アプリケーションにuserViewModelのレイヤーを追加する必要があります。 非常に剥がした例:

public HomeViewModel() 
{ 
    this.RefreshUsers(); 
    userListClick = new RelayCommand<SelectionChangedEventArgs>(_userListClick); 
    saveUser = new RelayCommand(saveUser, CanExecuteSaveUser); 
    selectedUserViewModel.PropertyChanged += SelectedUserOnPropertyChanged; 
} 

private void SelectedUserOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs) 
{ 
    if (propertyChangedEventArgs.PropertyName.Equals(nameof(UserViewModel.username))) 
    { 
     (saveUser as RelayCommand)?.RaiseCanExecuteChanged(); 
    } 
} 
+0

助けが必要です。私の問題は論理です。あなたの例: if(selectedUser.username == "foo") 特定の値をチェックしたくないので、プロパティがまったく変更されているかどうかを知りたいです。この場合、具体的には、有効化された、またはスーパーユーザーのブールが変更されました。 しかし、これは私が作業している最初のクラスです。私は他のクラスに移り、同じアプローチを使いたいと思います。私は、VIewModelでこのすべてを最も確実に処理していますが、このプロセスではModelと全く話していません。 –

+0

こんにちはRyan、私は上記の答えに追加の提案を追加しました。 user/UserViewModelでプロパティが変更されるたびにcanExecuteChangedイベントをトリガできると思います。ただし、コマンドのCanExecuteメソッドで無効な入力がないか確認してください。 –

+0

私は一晩中読んでいますが、INotifyPropertyChangedを実装するビューモデルクラスを作成するのが最善のアプローチです。このオブジェクトを使用してWCFサービスに渡してデータベースを更新する方法を理解するだけです。私はこの道を行く。提案していただきありがとうございます。 –

関連する問題