我在WPF中编写了MVVM代码。我希望如果用户没有选择任何内容并点击编辑按钮,它应该向用户显示消息以首先选择项目。我不明白的事情是如何在UpdateCommand之前进行此验证。我需要你的建议。谢谢。 这里的代码是:
class UserViewModel
{
private IList<User> _UsersList;
public User SelectedUser { get; set; }
public UserViewModel()
{
_UsersList = new List<User>
{
new User{UserId = 1,FirstName="Raj",LastName="Beniwal",City="Delhi",State="DEL",Country="INDIA"},
new User{UserId=2,FirstName="Mark",LastName="henry",City="New York", State="NY", Country="USA"},
new User{UserId=3,FirstName="Mahesh",LastName="Chand",City="Philadelphia", State="PHL", Country="USA"},
new User{UserId=4,FirstName="Vikash",LastName="Nanda",City="Noida", State="UP", Country="INDIA"},
new User{UserId=5,FirstName="Harsh",LastName="Kumar",City="Ghaziabad", State="UP", Country="INDIA"},
new User{UserId=6,FirstName="Reetesh",LastName="Tomar",City="Mumbai", State="MP", Country="INDIA"},
new User{UserId=7,FirstName="Deven",LastName="Verma",City="Palwal", State="HP", Country="INDIA"},
new User{UserId=8,FirstName="Ravi",LastName="Taneja",City="Delhi", State="DEL", Country="INDIA"}
};
if(SelectedUser == null) { ShowNoUserSelectedWarning(); } // How to put this before UpdateCommand To Warn User
}
public IList<User> Users
{
get { return _UsersList; }
set { _UsersList = value; }
}
public void ShowNoUserSelectedWarning()
{
System.Windows.MessageBox.Show("Warning");
}
private ICommand mUpdater;
public ICommand UpdateCommand
{
get
{
if (mUpdater == null)
mUpdater = new Updater();
return mUpdater;
}
set
{
mUpdater = value;
}
}
private class Updater : ICommand
{
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
}
#endregion
}
}
}
Xaml代码:
<dxdo:LayoutPanel Caption="Panel1" x:Name="Panel1">
<Grid Margin="0,0,0,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Name="UserGrid" Grid.Row="1" Margin="4,178,12,13" ItemsSource="{Binding Users}" SelectedItem="{Binding SelectedUser}">
<ListView.View>
<GridView x:Name="grdTest">
<GridViewColumn Header="UserId" DisplayMemberBinding="{Binding UserId}" Width="50"/>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="80" />
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="100" />
<GridViewColumn Header="City" DisplayMemberBinding="{Binding City}" Width="80" />
<GridViewColumn Header="State" DisplayMemberBinding="{Binding State}" Width="80" />
<GridViewColumn Header="Country" DisplayMemberBinding="{Binding Country}" Width="100" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</dxdo:LayoutPanel>
<dxdo:LayoutPanel x:Name="Panel3">
<Grid>
<StackPanel>
<Button Content="Edit" Height="23" HorizontalAlignment="Left"
VerticalAlignment="Top" Width="141" />
</StackPanel>
</Grid>
</dxdo:LayoutPanel>
<dxdo:LayoutPanel Caption="Panel2" x:Name="Panel2">
<Grid>
<StackPanel Margin="0,0,0,10">
<Grid Margin="0,0,0,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,7,0,0" Name="txtUserId" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=UserGrid,Path=SelectedItem.UserId}" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,35,0,0" Name="txtFirstName" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=UserGrid,Path=SelectedItem.FirstName}" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,62,0,0" Name="txtLastName" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=UserGrid,Path=SelectedItem.LastName}" />
<Label Content="UserId" Grid.Row="1" HorizontalAlignment="Left" Margin="12,12,0,274" Name="label1" />
<Label Content="Last Name" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,60,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="First Name" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,35,0,0" Name="label3" VerticalAlignment="Top" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,143,0,0" x:Name="txtCity" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.City, ElementName=UserGrid}" />
<Label Content="Country" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,141,0,0" x:Name="label2_Copy" VerticalAlignment="Top" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,88,0,0" x:Name="txtCountry" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.Country, ElementName=UserGrid}" />
<Label Content="City" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,86,0,0" x:Name="label2_Copy1" VerticalAlignment="Top" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,115,0,0" x:Name="txtSTate" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.State, ElementName=UserGrid}" />
<Label Content="State" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,113,0,0" x:Name="label2_Copy2" VerticalAlignment="Top" />
</Grid>
<Button Content="Update" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="310,40,0,0" Name="btnUpdate"
VerticalAlignment="Top" Width="141"
Command="{Binding Path=UpdateCommad}" />
<TextBox Width="166" Background="White" Height="33" HorizontalAlignment="Right" VerticalAlignment="Bottom" Text="{Binding Path=SelectedCustomer.LastName,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Grid>
</dxdo:LayoutPanel>
如果我的问题不明确,请询问。
答案 0 :(得分:2)
您想使用WPF命令模式。在您的Xaml中,您有一个像这样的物品控制......
<ListView Name="UserGrid" Grid.Row="1" Margin="4,178,12,13"
ItemsSource="{Binding Users}"
SelectedItem="{Binding SelectedUser}">
哪个好。和一个像这样声明的按钮......
<Button Content="Update" Grid.Row="1" Height="23"
HorizontalAlignment="Left" Margin="310,40,0,0" Name="btnUpdate"
VerticalAlignment="Top" Width="141"
Command="{Binding Path=UpdateCommad}" />
这也没关系。除非用户选择了用户,否则您不希望触发该按钮。要连接所有内容,您的View Model需要看起来像这样......
public class ViewModel : INotifyPropertyChanged
{
// declare the command
public ICommand UpdateCommand { get; set; }
public ViewModel()
{ // initialize the command
UpdateCommand = new RelayCommand(ExecuteUpdateCommand, CanExecuteUpdateCommand);
}
#region UpdateCommand callbacks
private bool CanExecuteUpdateCommand(object obj)
{
if (SelectedUser == null) return false;
return true;
}
private void ExecuteUpdateCommand(object obj)
{
Console.WriteLine("Executing the command");
}
#endregion // end of UpdateCommand callbacks
private User _selectedUser;
public User SelectedUser
{
[DebuggerStepThrough]
get { return _selectedUser; }
[DebuggerStepThrough]
set
{
if (value != _selectedUser)
{
_selectedUser = value;
OnPropertyChanged("SelectedUser");
}
}
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
此VM有一个名为SelectedUser的属性,该属性绑定到ListView,并将跟踪选择的任何用户。
VM还有一个属性UpdateCommand作为ICommand的实例。现在代码中缺少的是UpdateCommand需要实例化。这发生在构造函数中......
UpdateCommand = new RelayCommand(ExecuteUpdateCommand, CanExecuteUpdateCommand);
它被实例化为RelayCommand的一个实例。这两个代表在构造函数中被识别,您特别感兴趣的是CanExecute委托......
private bool CanExecuteUpdateCommand(object obj)
{
if (SelectedUser == null) return false;
return true;
}
这告诉WPF绑定引擎按钮不应该点亮,除非SelectedUser中有一个值。这就是你想要完成的事情。十分简单。你试图推出自己的ICommand版本,这很好,但为什么还要麻烦,考虑到它已被写入...
最后一部分是RelayCommand。它的作用在Josh Smith的开篇文章中进行了讨论:http://msdn.microsoft.com/en-us/magazine/dd419663.aspx但是为了快速参考,这里有来源......
using System;
using System.Windows.Input;
namespace Commanding
{
public class RelayCommand : ICommand
{ //http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
}
}
您可以将其粘贴到项目中。说完所有这些,使用这个简单的模型,您可以在WPF中的任何按钮或菜单项上使用命令模式。当CanExecute方法返回false时,UI元素被禁用,当它返回true时,UI元素被启用。