我是MVVM模式的新手.
我想知道为什么每次触发TextChanged()事件时,绑定的IsEnabled()属性都不会更改其状态. TextChanged()事件正在调用IsValid()以检查数据验证.
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] 举报,一经查实,本站将立刻删除。