MvvmCross对话框
我目前正在调查所有可能的解决方案,以便在用户需要做出决定时通知用户(即弹出对话框)。这是MVVM模式的一个常见问题,我正在尝试为MvvmCross框架解决它 可能的解决办法可以是:MvvmCross对话框,mvvm,dialog,modal-dialog,mvvmcross,Mvvm,Dialog,Modal Dialog,Mvvmcross,我目前正在调查所有可能的解决方案,以便在用户需要做出决定时通知用户(即弹出对话框)。这是MVVM模式的一个常见问题,我正在尝试为MvvmCross框架解决它 可能的解决办法可以是: 自定义MvxPresenter以显示对话框,但这在我看来有点难看 在核心项目中放置一个对话框界面,并使用控制反转将UI项目的实现注入到核心项目中 使用MvxMessenger插件并在Core和UI项目之间共享消息。听起来是个好主意,但开发起来可能更复杂 您有什么建议?对话框输入是一个有趣的主题,并不总是适合Mvv
- 自定义MvxPresenter以显示对话框,但这在我看来有点难看
- 在核心项目中放置一个对话框界面,并使用控制反转将UI项目的实现注入到核心项目中
- 使用MvxMessenger插件并在Core和UI项目之间共享消息。听起来是个好主意,但开发起来可能更复杂
您有什么建议?对话框输入是一个有趣的主题,并不总是适合Mvvm数据绑定的流程 通常,对话框的一些用例用于以下情况:
IInteractionRequest
接口,该接口可在数据绑定中使用,特别是在这种情况下
这方面的参考实施是:
public interface IInteractionRequest
{
event EventHandler<InteractionRequestedEventArgs> Raised;
}
public class InteractionRequestedEventArgs : EventArgs
{
public Action Callback { get; private set; }
public object Context { get; private set; }
public InteractionRequestedEventArgs(object context, Action callback)
{
Context = context;
Callback = callback;
}
}
public class InteractionRequest<T> : IInteractionRequest
{
public event EventHandler<InteractionRequestedEventArgs> Raised;
public void Raise(T context, Action<T> callback)
{
var handler = this.Raised;
if (handler != null)
{
handler(
this,
new InteractionRequestedEventArgs(
context,
() => callback(context)));
}
}
}
private InteractionRequest<Confirmation> _confirmCancelInteractionRequest = new InteractionRequest<Confirmation>();
public IInteractionRequest ConfirmCancelInteractionRequest
{
get
{
return _confirmCancelInteractionRequest;
}
}
其中,Confirmation
是一个简单的类,如:
public class Confirmation
{
public string Message { get; private set; }
public bool Confirmed { get; set; }
public Confirmation(string message)
{
Message = message;
}
}
要在视图中使用此选项,请执行以下操作:
MSDN链接显示了Xaml客户机如何使用行为绑定到该数据库,因此我在这里不作进一步介绍
在iOS for MvvmCross中,视图对象可能实现如下属性:
private MvxGeneralEventSubscription _confirmationSubscription;
private IInteractionRequest _confirmationInteraction;
public IInteractionRequest ConfirmationInteraction
{
get { return _confirmationInteraction; }
set
{
if (_confirmationInteraction == value)
return;
if (_confirmationSubscription != null)
_confirmationSubscription.Dispose();
_confirmationInteraction = value;
if (_confirmationInteraction != null)
_confirmationSubscription = _confirmationInteraction
.GetType()
.GetEvent("Raised")
.WeakSubscribe(_confirmationInteraction,
DoConfirmation);
}
}
此视图属性使用基于WeakReference
的事件订阅,以便将ViewModel引发的事件引导至视图消息框
-类型方法。使用WeakReference
非常重要,这样ViewModel就不会引用视图
——这可能会导致Xamarin.iOS中的内存泄漏问题。实际的MessageBox
类型方法本身相当简单,类似于:
private void DoConfirmation(InteractionRequestedEventArgs args)
{
var confirmation = (Confirmation)args.Context;
var alert = new UIAlertView();
alert.Title = "Bazinga";
alert.Message = confirmation.Message;
alert.AddButton("Yes");
alert.AddButton("No");
alert.Clicked += (sender, e) => {
var alertView = sender as UIAlertView;
if (e.ButtonIndex == 0)
{
// YES button
confirmation.Confirmed = true;
}
else if (e.ButtonIndex == 1)
{
// NO button
confirmation.Confirmed = false;
}
args.Callback();
};
}
属性可以绑定在一个流畅的绑定集中,如:
set.Bind(this)
.For(v => v.ConfirmationInteraction)
.To(vm => vm.ConfirmCancelInteractionRequest);
对于Android,可以使用类似的实现—这可能使用对话框片段
,也可能使用XML中的视图
进行绑定
注意:
- 我相信,如果我们进一步添加
IInteractionRequest
和InteractionRequestedEventArgs
定义,基本交互可以得到改进(在我看来)-但是,就这个答案的范围而言,我尽量保持“基本”实现,尽可能接近
- 一些附加的助手类也可以帮助显著简化视图订阅代码
你可以使用Brian Chance正如Eugene所说,使用用户交互插件。不幸的是,目前还没有Windows Phone实现,因此我在此期间使用了以下代码:
public class WindowsPhoneUserInteraction : IUserInteraction
{
public void Confirm(string message, Action okClicked, string title = null, string okButton = "OK", string cancelButton = "Cancel")
{
Confirm(message, confirmed =>
{
if (confirmed)
okClicked();
},
title, okButton, cancelButton);
}
public void Confirm(string message, Action<bool> answer, string title = null, string okButton = "OK", string cancelButton = "Cancel")
{
var mbResult = MessageBox.Show(message, title, MessageBoxButton.OKCancel);
if (answer != null)
answer(mbResult == MessageBoxResult.OK);
}
public Task<bool> ConfirmAsync(string message, string title = "", string okButton = "OK", string cancelButton = "Cancel")
{
var tcs = new TaskCompletionSource<bool>();
Confirm(message, tcs.SetResult, title, okButton, cancelButton);
return tcs.Task;
}
public void Alert(string message, Action done = null, string title = "", string okButton = "OK")
{
MessageBox.Show(message, title, MessageBoxButton.OK);
if (done != null)
done();
}
public Task AlertAsync(string message, string title = "", string okButton = "OK")
{
var tcs = new TaskCompletionSource<object>();
Alert(message, () => tcs.SetResult(null), title, okButton);
return tcs.Task;
}
public void Input(string message, Action<string> okClicked, string placeholder = null, string title = null, string okButton = "OK", string cancelButton = "Cancel", string initialText = null)
{
throw new NotImplementedException();
}
public void Input(string message, Action<bool, string> answer, string placeholder = null, string title = null, string okButton = "OK", string cancelButton = "Cancel", string initialText = null)
{
throw new NotImplementedException();
}
public Task<InputResponse> InputAsync(string message, string placeholder = null, string title = null, string okButton = "OK", string cancelButton = "Cancel", string initialText = null)
{
throw new NotImplementedException();
}
public void ConfirmThreeButtons(string message, Action<ConfirmThreeButtonsResponse> answer, string title = null, string positive = "Yes", string negative = "No", string neutral = "Maybe")
{
throw new NotImplementedException();
}
public Task<ConfirmThreeButtonsResponse> ConfirmThreeButtonsAsync(string message, string title = null, string positive = "Yes", string negative = "No", string neutral = "Maybe")
{
throw new NotImplementedException();
}
}
公共类WindowsPhoneUserInteraction:IUserInteraction
{
public void Confirm(字符串消息,操作已单击,字符串标题=null,字符串okButton=“确定”,字符串cancelButton=“取消”)
{
确认(消息,确认=>
{
如果(已确认)
okClicked();
},
标题、确认按钮、取消按钮);
}
public void Confirm(字符串消息、操作应答、字符串标题=null、字符串okButton=“确定”、字符串cancelButton=“取消”)
{
var mbResult=MessageBox.Show(消息、标题、MessageBoxButton.OKCancel);
如果(回答!=null)
回答(mbResult==MessageBoxResult.OK);
}
公共任务确认同步(字符串消息,字符串标题=“确定”,字符串取消按钮=“取消”)
{
var tcs=new TaskCompletionSource();
确认(消息、tcs.SetResult、标题、确定按钮、取消按钮);
返回tcs.Task;
}
公共作废警报(字符串消息,操作完成=null,字符串标题=,字符串okButton=“确定”)
{
MessageBox.Show(消息、标题、MessageBoxButton.OK);
如果(完成!=null)
完成();
}
公共任务AlertAsync(字符串消息,字符串标题=,字符串okButton=“确定”)
{
var tcs=new TaskCompletionSource();
警报(消息,()=>tcs.SetResult(null)、标题、OK按钮);
返回tcs.Task;
}
公共无效输入(字符串消息,单击操作OK,字符串占位符=null,字符串标题=null,字符串OK按钮=“OK”,字符串cancelButton=“取消”,字符串initialText=null)
{
抛出新的NotImplementedException();
}
公共无效输入(字符串消息、操作答案、字符串占位符=null、字符串标题=null、字符串okButton=“OK”、字符串cancelButton=“Cancel”、字符串initialText=null)
{
抛出新的NotImplementedException();
}
公共任务InputAsync(字符串消息,字符串占位符=null,字符串标题=null,字符串okButton=“确定”,字符串cancelButton=“取消”,字符串initialText=null)
{
抛出新的NotImplementedException();
}
public void ConfirmThreeButtons(字符串消息、操作应答、字符串标题=null、字符串
public class WindowsPhoneUserInteraction : IUserInteraction
{
public void Confirm(string message, Action okClicked, string title = null, string okButton = "OK", string cancelButton = "Cancel")
{
Confirm(message, confirmed =>
{
if (confirmed)
okClicked();
},
title, okButton, cancelButton);
}
public void Confirm(string message, Action<bool> answer, string title = null, string okButton = "OK", string cancelButton = "Cancel")
{
var mbResult = MessageBox.Show(message, title, MessageBoxButton.OKCancel);
if (answer != null)
answer(mbResult == MessageBoxResult.OK);
}
public Task<bool> ConfirmAsync(string message, string title = "", string okButton = "OK", string cancelButton = "Cancel")
{
var tcs = new TaskCompletionSource<bool>();
Confirm(message, tcs.SetResult, title, okButton, cancelButton);
return tcs.Task;
}
public void Alert(string message, Action done = null, string title = "", string okButton = "OK")
{
MessageBox.Show(message, title, MessageBoxButton.OK);
if (done != null)
done();
}
public Task AlertAsync(string message, string title = "", string okButton = "OK")
{
var tcs = new TaskCompletionSource<object>();
Alert(message, () => tcs.SetResult(null), title, okButton);
return tcs.Task;
}
public void Input(string message, Action<string> okClicked, string placeholder = null, string title = null, string okButton = "OK", string cancelButton = "Cancel", string initialText = null)
{
throw new NotImplementedException();
}
public void Input(string message, Action<bool, string> answer, string placeholder = null, string title = null, string okButton = "OK", string cancelButton = "Cancel", string initialText = null)
{
throw new NotImplementedException();
}
public Task<InputResponse> InputAsync(string message, string placeholder = null, string title = null, string okButton = "OK", string cancelButton = "Cancel", string initialText = null)
{
throw new NotImplementedException();
}
public void ConfirmThreeButtons(string message, Action<ConfirmThreeButtonsResponse> answer, string title = null, string positive = "Yes", string negative = "No", string neutral = "Maybe")
{
throw new NotImplementedException();
}
public Task<ConfirmThreeButtonsResponse> ConfirmThreeButtonsAsync(string message, string title = null, string positive = "Yes", string negative = "No", string neutral = "Maybe")
{
throw new NotImplementedException();
}
}
Mvx.RegisterSingleton<IUserInteraction>(new WindowsPhoneUserInteraction());