首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF如何更新CanExecute

WPF如何更新CanExecute
EN

Stack Overflow用户
提问于 2014-08-13 23:07:32
回答 2查看 10.2K关注 0票数 8

我有以下问题。

我有以下简单的xaml:

代码语言:javascript
复制
<TextBox Name="NameBox" Text ="{Binding Name}" />
<Button Content="Save" Command="{Binding SaveCommand}" CommandParameter="{Binding Entity}"  />

并将此窗口的DataContext绑定到以下视图模型

代码语言:javascript
复制
public class MyViewModel
{
    public SimpleModel Entity { get; set; }

    private ICommand _saveCommand;

    public ICommand SaveCommand { get { return _saveCommand ?? (_saveCommand = new MyCommand(OnSaveItem, parameter => CanSaveItem())); } }

    public void OnSaveItem(object parameter) 
    {
        // some code
    }

    public virtual bool CanSaveItem()
    {
        return !String.IsNullOrWhiteSpace(Entity.Name);
    }

}      

SimpleModel是

代码语言:javascript
复制
public class SimpleModel
{        
    public int Id { get; set; }

    public string Name { get; set; }       
}

这段代码大部分都是正确的,但是我不能让CanSaveItem方法正常工作。我不知道如何告诉SaveCommand ViewModel的属性被更改了。我知道我必须使用CanExecuteChanged或CommandManager.InvalidateRequerySuggested,我有时也尝试使用它们,但我不知道如何正确操作,也没有效果。你能帮我解决这个问题吗?

UPD。

代码语言:javascript
复制
public class MyCommand : ICommand
{        
    public MyCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _canExecute = canExecute;
        _execute = execute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {                       
        _execute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    private readonly Predicate<object> _canExecute;

    private readonly Action<object> _execute;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-08-14 03:20:49

看起来你正处于早期学习曲线上,这可能会令人困惑……有时对我来说也是。

无论如何,我对你所拥有的东西做了一些细微的改变,并解释了我对它们做了什么。

代码语言:javascript
复制
public class MyViewModel
{
    public SimpleModel Entity { get; set; }

    private MyCommand _saveCommand;

    public MyCommand SaveCommand { get { return _saveCommand ?? (_saveCommand = new MyCommand(OnSaveItem, parameter => CanSaveItem())); } }

    public MyViewModel()
    {
        //------ You need to create an instance of your entity to bind to
        Entity = new SimpleModel();

        //-- I added an event handler as your "Entity" object doesn't know 
        //-- about the button on the view model.  So when it has something
        //-- change, have it call anybody listening to its exposed event.
        Entity.SomethingChanged += MyMVVM_SomethingChanged;
    }

    void MyMVVM_SomethingChanged(object sender, EventArgs e)
    {
        // Tell our mvvm command object to re-check its CanExecute
        SaveCommand.RaiseCanExecuteChanged();
    }

    public void OnSaveItem(object parameter)
    {
        // some code
    }

    public virtual bool CanSaveItem()
    {
        //-- Checking directly to your Entity object
        return !String.IsNullOrWhiteSpace(Entity.Name);
    }
}


public class SimpleModel
{
    //-- Simple constructor to default some values so when you run
    //-- your form, you SHOULD see the values immediately to KNOW
    //-- the bindings are correctly talking to this entity. 
    public SimpleModel()
    {
        _name = "test1";
        _Id = 123;
    }

    //-- changed to public and private... and notice in the setter
    //-- to call this class's "somethingChanged" method
    private int _Id;
    public int Id
    {
        get { return _Id; }
        set
        {
            _Id = value;
            somethingChanged("Id");
        }
    }

    private string _name;
    public string Name 
    { get { return _name; }
        set { _name = value;
                somethingChanged( "Name" );
        }
    }

    //-- Expose publicly for anything else to listen to (i.e. your view model)
    public event EventHandler SomethingChanged;

    //-- So, when any property above changes, it calls this method with whatever
    //-- its property is just as a reference.  Then checks.  Is there anything
    //-- listening to our exposed event handler?  If so, pass the information on
    private void somethingChanged( string whatProperty)
    {
        // if something is listening
        if (SomethingChanged != null)
            SomethingChanged(whatProperty, null);
    }


}


public class MyCommand : ICommand
{
    public MyCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _canExecute = canExecute;
        _execute = execute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    private readonly Predicate<object> _canExecute;

    private readonly Action<object> _execute;

    //-- Change to the event handler definition, just expose it
    public event EventHandler CanExecuteChanged;

    //-- Now expose this method so your mvvm can call it and it rechecks 
    //-- it's own CanExecute reference
    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, new EventArgs());
    }
}

最后,表单中的绑定。我不知道您是如何将视图的"DataContext“设置为视图模型的,但假设这些都是正确的,没有问题,请将文本框和命令按钮调整为如下所示

代码语言:javascript
复制
<TextBox Name="NameBox" Text ="{Binding Entity.Name, 
    NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}"  />

<Button Content="Save" Command="{Binding SaveCommand}" CommandParameter="{Binding Entity}"  />

注意,文本绑定是绑定到MVVM上的" Entity“对象,然后是实体对象的".Name”属性。这里最重要的是UpdateSourceTrigger。这会强制在每次字符更改时重新更新数据绑定,因此一旦删除最后一个字符,或者开始键入第一个字符,"Save“按钮就会相应地刷新。

票数 11
EN

Stack Overflow用户

发布于 2014-08-13 23:14:46

我会尝试调用CommandManager.InvalidateRequerySuggested.

http://msdn.microsoft.com/en-us/library/system.windows.input.commandmanager.invalidaterequerysuggested(v=vs.110).aspx

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25289753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档