0

我在 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>

如果我的问题不清楚,请询问。

4

1 回答 1

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}"  />

这也很好。除非用户选择了用户,否则您不希望按钮触发。要将所有内容连接起来,您的视图模型需要看起来像这样......

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 元素被启用。

于 2013-08-27T19:07:50.317 回答