如何在另一个方法上继续冻结一个方法的执行,并在发生某些事件时返回原始方法。 (我基本上试图将丑陋的MessageBox.Show()替换为更多的MVVM版本)
请参阅以下示例:
private void ButtonClickRelayAction()
{
DoMyMethod();
}
private void DoMyMethod() <~~ I dont want to change this method if it can be helped
{
Logic1();
Logic2();
var response1 = ShowMvvmMessageBox("Hello", "Please confirm"); <~ has to be run in the UI thread
if (response1 == "Cancel")
return;
ContinueLogic3();
var response2 = ShowMvvmMessageBox("Hello", "Please confirm again"); <~ has to be run in the UI thread
if (response2 == "Cancel")
return;
ContinueLogic4();
}
private void ShowMvvmMessageBox(string question, string caption)
{
interactionRequest = new InteractionRequest<IConfirmation>(), myMessage, title);
interactionRequest.Raise(new Confirmation { Content = mainText, Title = title}, SomeAction<IConfirmation>);
// This method ends before the user has clicked the button.
// The SomeAction<IConfirmation> delegate is a callback when the user has clicked it, how do I handle it and continue execution of DoMyMethod from where it left off?
// Everything i've tried freezes the UI thread..
}
提前致谢: - )
P.S。随意将我的逻辑分开并保持残酷。
答案 0 :(得分:0)
我为你做了一个小例子,你可以看到如何解决你的问题。
我有以下ViewModel
internal class MainWindowViewModel
{
private readonly DialogService dialogService;
private ICommand dummyCommand;
public MainWindowViewModel()
{
dialogService = new DialogService();
}
public ICommand DummyCommand
{
get { return dummyCommand ?? (dummyCommand = new RelayCommand<object>(p => Dummy())); }
}
private async void Dummy()
{
Logic1();
await dialogService.ShowMvvmMessageBox("Question1?", "Q1?");
Logic2();
await dialogService.ShowMvvmMessageBox("Question2", "Q2");
Logic3();
}
private void Logic1()
{
// So some logic here
}
private void Logic2()
{
// So some logic here
}
private void Logic3()
{
// So some logic here
}
}
DialogService
看起来像:
internal class DialogService
{
public async Task<bool> ShowMvvmMessageBox(string question, string caption)
{
bool res = await Task<bool>.Factory.StartNew(() =>
{
MessageBoxResult result = MessageBox.Show(question, caption, MessageBoxButton.YesNo);
return result == MessageBoxResult.Yes;
});
return res;
}
}
答案 1 :(得分:0)
我认为您可能正在寻找的是一个带有Ok-Cancel按钮的Dialogue Box(或等效物),在需要时显示它,然后处理它的返回值。正确的ViewModel实例我相信你已经使用DataContext绑定了正确的视图。
这个想法可能在代码中看起来像这样:
public partial class MainWindow : Window
{
MyViewModel vm = new MyViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = vm;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
DXDialog d = new DXDialog("Information", DialogButtons.OkCancel,true);
PropertyGrid p = new PropertyGrid() { DataContext = vm }; // Dialog view and Main view are both bound to the same viewmodel instance here.
d.Content = p;
d.SizeToContent = System.Windows.SizeToContent.WidthAndHeight;
d.Owner = this;
d.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
var result = d.ShowDialog();
if (result == true)
{
this.button1.Content = vm.Customer1;
}
else
{
// write the logic for "Cancel" button click. You can revert the Datacontext to the earlier value
//of the ViewModel by having saved its cloned object in this same method
}
}
}
P.S:DXDialogue是一个DevExpress控件。你需要你的WPF等价物,我敢肯定。
答案 2 :(得分:0)
我这样做非常简单且符合MVVM:我在ViewModel和后面的View代码中定义事件,我显示MessageBox并设置EventArgs参数,以便ViewModel知道在View中按下了什么。我在View的DataContextChanged中附加了该事件的方法。另一种方法是使用完全分离的消息传递系统,但它的工作量要大得多。
Public Class GenericEventArgs(Of TEventData)
Inherits EventArgs
Public Sub New(Optional eventData As TEventData = Nothing)
Me.EventData = eventData
End Sub
Public Property EventData As TEventData
End Class
Class MainWindow
Private Sub Me_DataContextChanged(sender As Object, e As DependencyPropertyChangedEventArgs) Handles Me.DataContextChanged
Dim mainWindowVM = DirectCast(DataContext, MainWindowViewModel)
AddHandler mainWindowVM.SavingChanges, AddressOf MainWindowViewModel_SavingChanges
End Sub
Private Sub MainWindowViewModel_SavingChanges(sender As Object, e As GenericEventArgs(Of Boolean?))
If MessageBox.Show("Save changes?",
"Document was changed",
MessageBoxButton.YesNo,
MessageBoxImage.Exclamation) = MessageBoxResult.Yes Then
e.EventData = True
Else
e.EventData = False
End If
End Sub
End Class
Class MainWindowViewModel
Public Event SavingChanges As EventHandler(Of GenericEventArgs(Of Boolean?))
Public Sub SaveChanges()
Dim e As New GenericEventArgs(Of Boolean?)
RaiseEvent SavingChanges(Me, e)
If e.EventData = True Then
'User want to save changes
Else
'User dont want to save changes
End If
End Sub
End Class