我认为有更好的方法来完成你正在做的事情。为了使这更符合MVVM,这是我的做法... 首先,我使用Caliburn Micro来处理我的MVVM和MEF。所以我们首先有两个接口:
internal interface IDialogViewModel
{
event EventHandler Closed;
}
接下来的界面将帮助您获取对话框的结果。
public interface IDialogManager
{
Task<TResult> ShowDialog<TResult>(DialogViewModel<TResult> viewModel);
Task ShowDialog(DialogViewModel viewModel);
}
这些接口的实现是:
public abstract class DialogViewModel : Screen, IDialogViewModel
{
private readonly TaskCompletionSource<int> tcs;
internal Task Task { get { return tcs.Task; } }
protected DialogViewModel()
{
tcs = new TaskCompletionSource<int>();
}
protected void Close()
{
tcs.SetResult(0);
var handler = Closed;
if (handler != null)
handler(this, EventArgs.Empty);
}
public event EventHandler Closed;
}
public abstract class DialogViewModel<TResult> : Screen, IDialogViewModel
{
private readonly TaskCompletionSource<TResult> tcs;
internal Task<TResult> Task { get { return tcs.Task; } }
protected DialogViewModel()
{
tcs = new TaskCompletionSource<TResult>();
}
protected void Close(TResult result)
{
tcs.SetResult(result);
var handler = Closed;
if (handler != null)
handler(this, EventArgs.Empty);
}
public event EventHandler Closed;
}
经理类是
[Export(typeof(IDialogManager))]
public class DialogManager : IDialogManager
{
public async Task ShowDialog(DialogViewModel viewModel)
{
var viewType = ViewLocator.LocateTypeForModelType(viewModel.GetType(), null, null);
var dialog = (BaseMetroDialog)Activator.CreateInstance(viewType);
if (dialog == null)
{
throw new InvalidOperationException(
String.Format("The view {0} belonging to view model {1} " +
"does not inherit from {2}",
viewType,
viewModel.GetType(),
typeof(BaseMetroDialog)));
}
dialog.DataContext = viewModel;
MetroWindow firstMetroWindow =
Application.Current.Windows.OfType<MetroWindow>().First();
await firstMetroWindow.ShowMetroDialogAsync(dialog);
await viewModel.Task;
await firstMetroWindow.HideMetroDialogAsync(dialog);
}
public async Task<TResult> ShowDialog<TResult>(DialogViewModel<TResult> viewModel)
{
var viewType = ViewLocator.LocateTypeForModelType(viewModel.GetType(), null, null);
var dialog = (BaseMetroDialog)Activator.CreateInstance(viewType);
if (dialog == null)
{
throw new InvalidOperationException(
String.Format("The view {0} belonging to view model {1} " +
"does not inherit from {2}",
viewType,
viewModel.GetType(),
typeof(BaseMetroDialog)));
}
dialog.DataContext = viewModel;
MetroWindow firstMetroWindow = Application.Current.Windows.OfType<MetroWindow>().First();
await firstMetroWindow.ShowMetroDialogAsync(dialog);
TResult result = await viewModel.Task;
await firstMetroWindow.HideMetroDialogAsync(dialog);
return result;
}
}
我们还有消息框设置。
public class MessageBoxSettings
{
public MessageBoxSettings()
{
this.AffirmativeButtonText = "OK";
this.NegativeButtonText = "Cancel";
this.MessageDialogStyle = MessageDialogStyle.AffirmativeAndNegative;
this.MetroColorDialogScheme = MetroDialogColorScheme.Theme;
this.Animation = false;
}
public MessageDialogStyle MessageDialogStyle { get; set; }
public MetroDialogColorScheme MetroColorDialogScheme { get; set; }
public string AffirmativeButtonText { get; set; }
public string NegativeButtonText { get; set; }
public string FirstAuxillaryButtonText { get; set; }
public string SecondAuxiliaryButtonText { get; set; }
public bool Animation { get; set; }
}
现在使用上述代码的视图和视图模型为:
public class MessageBoxViewModel : DialogViewModel<MessageDialogResult>
{
private MessageBoxSettings settings;
#region Initialisation.
public MessageBoxViewModel() { }
public MessageBoxViewModel(string title, string message)
{
this.Title = title;
this.DialogBody = message;
if (this.settings == null)
this.settings = new MessageBoxSettings();
SetDialogVisuals();
}
public MessageBoxViewModel(string title, string message, MessageBoxSettings settings)
{
this.Title = title;
this.DialogBody = message;
this.settings = settings;
SetDialogVisuals();
}
#endregion // Initialisation.
#region Class Methods.
private void SetDialogVisuals()
{
switch (settings.MessageDialogStyle)
{
case MessageDialogStyle.Affirmative:
this.AffirmativeButtonVisibility = Visibility.Visible;
this.NegativeButtonVisibility = Visibility.Collapsed;
this.FirstAuxillaryButtonVisibility = Visibility.Collapsed;
this.SecondAuxillaryButtonVisibility = Visibility.Collapsed;
break;
case MessageDialogStyle.AffirmativeAndNegative:
this.AffirmativeButtonVisibility = Visibility.Visible;
this.NegativeButtonVisibility = Visibility.Visible;
this.FirstAuxillaryButtonVisibility = Visibility.Collapsed;
this.SecondAuxillaryButtonVisibility = Visibility.Collapsed;
break;
case MessageDialogStyle.AffirmativeAndNegativeAndDoubleAuxiliary:
this.AffirmativeButtonVisibility = Visibility.Visible;
this.NegativeButtonVisibility = Visibility.Visible;
this.FirstAuxillaryButtonVisibility = Visibility.Visible;
this.SecondAuxillaryButtonVisibility = Visibility.Visible;
break;
case MessageDialogStyle.AffirmativeAndNegativeAndSingleAuxiliary:
this.AffirmativeButtonVisibility = Visibility.Visible;
this.NegativeButtonVisibility = Visibility.Visible;
this.FirstAuxillaryButtonVisibility = Visibility.Visible;
this.SecondAuxillaryButtonVisibility = Visibility.Collapsed;
break;
default:
break;
}
this.AffirmativeButtonText = settings.AffirmativeButtonText;
this.NegativeButtonText = settings.NegativeButtonText;
this.FirstAuxillaryButtonText = settings.FirstAuxillaryButtonText;
this.SecondAuxiliaryButtonText = settings.SecondAuxiliaryButtonText;
string name = MahApps.Metro.ThemeManager.DetectAppStyle(Application.Current).Item2.Name;
this.Background = settings.MetroColorDialogScheme == MetroDialogColorScheme.Theme ?
MahApps.Metro.ThemeManager.Accents
.Where(a => a.Name.CompareNoCase(name))
.First().Resources["HighlightBrush"] as SolidColorBrush :
new SolidColorBrush(System.Windows.Media.Colors.White);
}
public void AffirmativeButtonClick()
{
Close(MessageDialogResult.Affirmative);
}
public void NegativeButtonClick()
{
Close(MessageDialogResult.Negative);
}
public void FirstAuxillaryButtonClick()
{
Close(MessageDialogResult.FirstAuxiliary);
}
public void SecondAuxillaryButtonClick()
{
Close(MessageDialogResult.SecondAuxiliary);
}
#endregion // Class Methods.
#region Properties.
private string title;
public string Title
{
get { return title; }
set
{
if (title == value)
return;
title = value;
NotifyOfPropertyChange(() => Title);
}
}
private string dialogBody;
public string DialogBody
{
get { return dialogBody; }
set
{
if (dialogBody == value)
return;
dialogBody = value;
NotifyOfPropertyChange(() => DialogBody);
}
}
private MessageDialogStyle messageDialogStyle =
MessageDialogStyle.AffirmativeAndNegative;
public MessageDialogStyle MessageDialogStyle
{
get { return messageDialogStyle; }
set
{
if (messageDialogStyle == value)
return;
messageDialogStyle = value;
NotifyOfPropertyChange(() => MessageDialogStyle);
}
}
private SolidColorBrush background;
public SolidColorBrush Background
{
get { return background; }
set
{
if (background == value)
return;
background = value;
NotifyOfPropertyChange(() => Background);
}
}
private string affirmativeButtonText = "OK";
public string AffirmativeButtonText
{
get { return affirmativeButtonText; }
set
{
if (affirmativeButtonText == value)
return;
affirmativeButtonText = value;
NotifyOfPropertyChange(() => AffirmativeButtonText);
}
}
private Visibility affirmativeButtonVisibility = Visibility.Visible;
public Visibility AffirmativeButtonVisibility
{
get { return affirmativeButtonVisibility = Visibility.Visible; }
set
{
if (affirmativeButtonVisibility == value)
return;
affirmativeButtonVisibility = value;
NotifyOfPropertyChange(() => AffirmativeButtonVisibility);
}
}
private string negativeButtonText = "Cancel";
public string NegativeButtonText
{
get { return negativeButtonText; }
set
{
if (negativeButtonText == value)
return;
negativeButtonText = value;
NotifyOfPropertyChange(() => NegativeButtonText);
}
}
private Visibility negativeButtonVisibility = Visibility.Visible;
public Visibility NegativeButtonVisibility
{
get { return negativeButtonVisibility; }
set
{
if (negativeButtonVisibility == value)
return;
negativeButtonVisibility = value;
NotifyOfPropertyChange(() => NegativeButtonVisibility);
}
}
private string firstAuxillaryButtonText;
public string FirstAuxillaryButtonText
{
get { return firstAuxillaryButtonText; }
set
{
if (firstAuxillaryButtonText == value)
return;
firstAuxillaryButtonText = value;
NotifyOfPropertyChange(() => FirstAuxillaryButtonText);
}
}
private Visibility firstAuxillaryButtonVisibility = Visibility.Collapsed;
public Visibility FirstAuxillaryButtonVisibility
{
get { return firstAuxillaryButtonVisibility; }
set
{
if (firstAuxillaryButtonVisibility == value)
return;
firstAuxillaryButtonVisibility = value;
NotifyOfPropertyChange(() => FirstAuxillaryButtonVisibility);
}
}
private string secondAuxiliaryButtonText;
public string SecondAuxiliaryButtonText
{
get { return secondAuxiliaryButtonText; }
set
{
if (secondAuxiliaryButtonText == value)
return;
secondAuxiliaryButtonText = value;
NotifyOfPropertyChange(() => SecondAuxiliaryButtonText);
}
}
private Visibility secondAuxillaryButtonVisibility = Visibility.Collapsed;
public Visibility SecondAuxillaryButtonVisibility
{
get { return secondAuxillaryButtonVisibility; }
set
{
if (secondAuxillaryButtonVisibility == value)
return;
secondAuxillaryButtonVisibility = value;
NotifyOfPropertyChange(() => SecondAuxillaryButtonVisibility);
}
}
#endregion // Properties.
}
视图是:
<MahAppsDialogs:CustomDialog
x:Class="GambitFramework.Core.MessageBox.MessageBoxView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Caliburn="http://www.caliburnproject.org"
xmlns:MahApps="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:Local="clr-namespace:GambitFramework.Core.MessageBox"
xmlns:Converters="clr-namespace:GambitFramework.Core.Converters;assembly=GambitFramework"
xmlns:MahAppsDialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
Title="{Binding Title}">
<MahAppsDialogs:CustomDialog.Content>
<TextBlock Text="{Binding DialogBody}"
Margin="0,5,0,0"
TextWrapping="Wrap"/>
</MahAppsDialogs:CustomDialog.Content>
<MahAppsDialogs:CustomDialog.DialogBottom>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="25*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,0,0,0">
<Button x:Name="AffirmativeButton"
Content="{Binding AffirmativeButtonText}"
Visibility="{Binding AffirmativeButtonVisibility}"
Style="{StaticResource AccentedSquareButtonStyle}"
Caliburn:Message.Attach="[Event Click] = [Action AffirmativeButtonClick()]"
MinWidth="75"
Padding="15,0"
Margin="5,10,0,5"/>
<Button x:Name="NegativeButton"
Content="{Binding NegativeButtonText}"
Visibility="{Binding NegativeButtonVisibility}"
Caliburn:Message.Attach="[Event Click] = [Action NegativeButtonClick()]"
MinWidth="75"
Padding="15,0"
Margin="10,10,0,5"/>
<Button x:Name="FirstAuxiliaryButton"
Content="{Binding FirstAuxillaryButtonText}"
Visibility="{Binding FirstAuxillaryButtonVisibility}"
Caliburn:Message.Attach="[Event Click] = [Action FirstAuxillaryButtonClick()]"
MinWidth="75"
Padding="15,0"
Margin="5,10,0,5"/>
<Button x:Name="SecondAuxiliaryButton"
Content="{Binding SecondAuxiliaryButtonText}"
Visibility="{Binding SecondAuxillaryButtonVisibility}"
Caliburn:Message.Attach="[Event Click] = [Action SecondAuxillaryButtonClick()]"
MinWidth="75"
Padding="15,0"
Margin="5,10,0,5"/>
</StackPanel>
</Grid>
</MahAppsDialogs:CustomDialog.DialogBottom>
</MahAppsDialogs:CustomDialog>
这个视图没有任何代码。这段代码可以按照以下方式使用:
MessageBoxSettings settings = new MessageBoxSettings()
{
MessageDialogStyle = MessageDialogStyle.AffirmativeAndNegative,
MetroColorDialogScheme = MetroDialogColorScheme.Accented,
AffirmativeButtonText = "Delete",
NegativeButtonText = "Cancel"
};
string message = String.Format(
"Are you sure you want to delete back test \"{0}\" {1}",
SelectedBackTest.Name,
SelectedBackTest.LastRun == null ?
String.Empty :
String.Format("which was late run on {0:G}?", SelectedBackTest.LastRun));
MessageDialogResult r = await dialogManager
.ShowDialog<MessageDialogResult>(
new MessageBoxViewModel("Confirm Delete", message, settings));
if (r == MessageDialogResult.Affirmative)
{
...
}
我希望这能有所帮助。