我在XAML中绑定一个按钮来更新数据库中的用户。我想利用CanExecute仅在对ViewModel上的属性进行更改后才启用该按钮。
我正在使用Entity Framework和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中绑定的值来控制启用状态我的按钮。
我似乎找不到使用Entity Generated类来处理这个问题的方法。任何帮助都会很棒。
答案 0 :(得分:1)
如果我理解正确,您希望尽快启用连接到saveUser命令的按钮,因为对selectedUser进行了更改?
我相信可以绑定RelayCommand(saveUser,someCommand)并让someCommand返回一个值,我可以在我的XAML中绑定它来控制我的按钮的启用状态。
使用CompositeCommands(MSDN Documentation)可以实现这一点。在这里,您可以调用方法“RegisterCommand”并传递第二个命令,该命令会影响连接到CompositeCommand的Button的行为。因此,如果注册的Button返回CanExecute == false,则该按钮将被禁用。
但是你也可以在RelayCommand中添加一个CanExecute方法,如果实体具有正确的值,则检查它。 例如,CanExecute方法可以检查例如userName:
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,您可以在其中直接处理对User属性所做的所有更改。这些属性的更改可以触发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();
}
}