如何解决MVVM我可以在行为中实施逻辑代码还是应该将其全部放入VM中的绑定命令?
我有输入完成命令的行为,该命令验证输入内部的数据,以及我保存在ViewModel中的逻辑。而且,当我完成输入后,我需要将焦点更改为下一个输入(下一个输入没有x:Name,因为它位于DataTemplate内部)。要更改焦点,我需要下一个条目的对象,我可以通过他的父对象在行为文件(而不是VM)中找到该对象。是在MVVM中执行此操作的正确方法,还是我应该通过参数将条目对象传递给VM,并找到其父项,然后在VM中找到下一个条目?
行为:
using System.Windows.Input;
using Xamarin.Forms;
namespace RollPositioningMobile.ViewModels.Behaviors
{
public class EntryCompletedBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry bindable)
{
base.OnAttachedTo(bindable);
AssociatedObject = bindable;
bindable.BindingContextChanged += Bindable_BindingContextChanged;
bindable.Completed += Bindable_Completed;
}
protected override void OnDetachingFrom(Entry bindable)
{
base.OnDetachingFrom(bindable);
bindable.BindingContextChanged -= Bindable_BindingContextChanged;
bindable.Completed -= Bindable_Completed;
AssociatedObject = null;
}
private void Bindable_BindingContextChanged(object sender,System.EventArgs e)
{
OnBindingContextChanged();
}
private void Bindable_Completed(object sender,System.EventArgs e)
{
if (Command == null) return;
Entry entry = (Entry)sender;
Grid circularEntriesGrid;
//If this handler was invoked from the RequiredValueEntry,//focus on the next Entry mechanic is different
if (entry.TabIndex == 0)
{
//First we need to define the main Grid,//and then find subgrid inside of the main
Grid mainGrid = (Grid)entry.Parent.Parent;
circularEntriesGrid = mainGrid.FindByName<Grid>("CircularEntriesGrid");
}
else
{
//Get the Frame parent and then the Grid parent of the Entry
circularEntriesGrid = (Grid)entry.Parent.Parent;
//Check for last entry
if (circularEntriesGrid.Children.Count == entry.TabIndex)
return;
}
//Execution of the input data validation commands
if (Command.CanExecute(entry.TabIndex))
Command.Execute(entry.TabIndex);
//Set focus on the next Entry
if ((bool)CommandParameter)
{
var nextEntryFrame = (Frame)circularEntriesGrid.Children[entry.TabIndex];
var nextEntry = (Entry)nextEntryFrame.Content;
nextEntry.Focus();
}
else
{
entry.Focus();
}
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
BindingContext = AssociatedObject.BindingContext;
}
public Entry AssociatedObject { get; private set; }
public static readonly BindableProperty CommandProperty =
BindableProperty.Create("Command",typeof(ICommand),typeof(EntryCompletedBehavior),null);
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty,value); }
}
public static readonly BindableProperty CommandParameterProperty =
BindableProperty.Create("CommandParameter",typeof(object),null);
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty,value); }
}
}
}
VM部分:
public ICommand EntryCompletedCommand { get; protected set; }
void EntryCompleted(object param)
{
var entryId = (int)param;
//Validating required value
if (entryId == 0)
{
RequiredValueIsValid = true;
if (RequiredValue <= 0)
{
Application.Current.MainPage.DisplayAlert("Error",$"Required value cannot be equals to {RequiredValue}","OK");
RequiredValueIsValid = false;
}
return;
}
//Validating actual values
var entry = ActualValues[entryId - 1];
var value = entry.Value;
if (value < 0 || Math.Abs(value - RequiredValue) > Measurment.MaxOffset)
{
entry.Value = entry.OldValue;
Application.Current.MainPage.DisplayAlert("Error",$"The actual and the required value should not differ more than {Measurment.MaxOffset}","OK");
entry.IsValid = false;
return;
}
entry.IsValid = true;
RequiredValueIsValid = true;
entry.OldValue = entry.Value;
}
解决方法
我可以在行为中实施逻辑代码还是应该将其全部放入VM中的绑定命令?
由于您已使用MVVM,因此最好处理ViewModel中的逻辑。我们总是对元素本身进行一些自定义。
在您的情况下,必须将条目作为参数传递给ViewModel。您可以将 IsFocused 的值绑定到Model的属性,然后直接在VM中处理它。
这里有一个类似的thread,我提供了一个完整的解决方案。希望对您有帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。