微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

绑定的Button.IsEnabled()属性无法正常工作

我是MVVM模式的新手.

我想知道为什么每次触发TextChanged()事件时,绑定的IsEnabled()属性都不会更改其状态. TextChanged()事件正在调用IsValid()以检查数据验证.

我有这个简单的viewmodel类

public class myviewmodel : viewmodel
{
    public bool IsOk { get; set; }
    public RelayCommand OnValidateExecute { get; set; }

    public myviewmodel()
    {
        OnValidateExecute = new RelayCommand(p => IsValid(), p => true);
    }

    public bool IsValid()
    {
        // other codes
        IsOk = MethodName();
        NotifyPropertyChanged("IsOk");
    }
}

我在IsValid()上设置了一个断点,代码运行正常.我想知道为什么IsEnabled属性无法按预期工作.

这是我的XAML代码

<TextBox ...other propeties here....>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="TextChanged">
            <i:InvokeCommandAction Command="{Binding OnValidateExecute}">
            </i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

<Button x:Name="btnSave" IsEnabled="{Binding IsOk, Mode=TwoWay}" 
            ...other propeties here....>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <i:InvokeCommandAction Command="{Binding OnSaveExecute}">
            </i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

我想要的是当IsOk属性为false时,该按钮应为disabled,否则为Enabled.

我的数据绑定有问题吗?如果以前曾问过这个问题,请帮助我重定向到它.

更新1

我在此代码中遇到的另一个问题是,在文本框上设置值之前,首先触发IsValid()函数.这是一个示例,假设文本框的起始值为0,当我将其更改为9时,将要检查的值为先前的值0而不是9.知道为什么会这样吗?绑定有问题吗?

解决方法:

这是答案,其中包括我的MVVM Framework的重要部分.除此之外,我还添加了一些额外的功能.我不能把所有图书馆都放在这里.但是我相信这会有所帮助.

如果使用Commanding,则应注意ICommand接口中的CanExecuteChanged.属性更改时应触发此命令. (我不使用RelayCommand,它是3.party.)

使用我的DCommand :)这是最重要的部分

它易于实现,
并具有FirePropertyChanged方法.如果它不为null,则触发ICommand的CanExecuteChanged.

一个示例命令

匿名语法

   DCommand commandPost=new DCommand(()=>{
      //Todo:Command's real execute method Post()
        },
      ()=>
      {
         return this.TextBoxBoundProperty.IsValid;
      }
    )

非匿名语法

    DCommand commandPost=(Post,Validate);

除此之外,您还应在viewmodel的ctor中通过以下方法触发canexecutechanged.

    this.PropertyChanged += (sender, prop) =>
          {
        //I preffered canExcuteChange for any property changes for my viewmodel class. You Could put your own logic. if(prop.PropertyName.equals("thisone"));
        //Just works for this class's property changed
                this.InvokeOnClasspropertyChange(prop.PropertyName, () =>
                {
                    this.commandPost.FirePropertyChanged();
                });
          }

如果该属性viewmodel类的属性,则InvokeOnClasspropertyChange起作用.

    public static void InvokeOnClasspropertyChange(this object instance,string PropertyName,Action action)
    {
        Type type = instance.GetType();
        var fulllist = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(w => w.DeclaringType == type).ToList();
        if (fulllist.Select(p => p.Name).Contains(PropertyName))
        {
            action.Invoke();
        }
    }

上面的代码显示了InvokeOnClasspropertyChange扩展方法.
下图显示了我的DCommand实现ICommand.

   public class DCommand :ICommand
    {
    public void FirePropertyChanged()
    {
        if (CanExecuteChanged!=null)
        CanExecuteChanged(this, EventArgs.Empty);            
    }

    Func<bool> CanExecuteFunc { get; set; }
    Action<object> Action { get; set; }


    public DCommand(Action<object> executeMethod)
    {
        this.Action = executeMethod;            
    }

    public DCommand(Action executeMethod)
    {
        this.Action = new Action<object>(
            (prm) =>
            {
                executeMethod.Invoke();
            }
            );
    }

    public DCommand(Action<object> executeMethod, Func<bool> canExecuteMethod)
        : this(executeMethod)
    {            
        this.CanExecuteFunc = canExecuteMethod;            
    }

    public DCommand(Action executeMethod, Func<bool> canExecuteMethod)
        : this(executeMethod)
    {
        this.CanExecuteFunc = canExecuteMethod;
    }

    public bool CanExecute(object parameter=null)
    {
        if (CanExecuteFunc == null)
            return true;

        return CanExecuteFunc.Invoke();
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter=null)
    {

        if (CanExecuteFunc == null || CanExecute(parameter))
        {
            Action.Invoke(parameter);                
        }

    }
}

毕竟,
如果要在文本框的文本立即更改时更改viewmodel属性,则应通过这种方式进行绑定.

Text =“ {Binding BoundProperty,Mode = TwoWay,UpdateSourceTrigger = PropertyChanged}”

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐