如何使用 EF6 生成的类识别对对象的更改以实现 CanExecute?



我正在 XAML 中绑定一个按钮来更新数据库中的用户。 我想利用 CanExecute 仅在对 ViewModel 上的属性进行更改后启用该按钮。

我正在使用实体框架和 WCF 数据服务来执行我的 CRUD 操作。

模型类

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

周转基金服务

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

我相信可以绑定 RelayCommand(saveUser,someCommand(并让someCommand返回一个值,我可以在 XAML 中绑定该值以控制按钮的启用状态。

我似乎找不到使用实体生成的类来处理这个问题的方法。 任何帮助都会很棒。

如果我理解正确,您想尽快启用连接到 saveUser 命令的按钮,因为对所选用户进行了更改?

我相信可以绑定 RelayCommand(saveUser,someCommand(并让 someCommand 返回一个值,我可以在 XAML 中绑定该值以控制按钮的启用状态。

这可以通过 CompositeCommands (MSDN 文档( 实现。在这里,您可以调用方法"RegisterCommand"并传递第二个命令,该命令会影响连接到复合命令的按钮的行为。因此,如果注册的按钮返回 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 服务之间添加一个额外的层,这是一种 UserViewModel,您可以在其中直接处理对用户属性所做的所有更改。这些属性中的更改可以触发 RelayCommand 的 RaiseCanExecuteChanged 方法。

我希望这有帮助,如果我误解了你,请提供进一步的问题解释。

编辑:

在您发表评论之后,我认为您可以实现 INotifyPropertyChanged 事件并订阅这些事件。为此,有必要向应用程序添加额外的用户视图模型层。 非常精简的例子:

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

最新更新