如何解决使用 MVVM 的 WPF 自定义模态对话框
问题
我正在努力将按下哪个按钮的结果从我的 CustomDialogUserControl.xaml.cs
传递到我的 CustomDialogService.cs
。
背景
我可以通过我的 MessageBox.Show
使用 CustomDialogService.cs
,一切都很好,看起来像这样:
我创建了自己的 CustomDialogUserControl
来实现覆盖窗口,方法是在我的应用程序窗口中使用 x:Name="MainGrid"
并在需要对话框时以编程方式添加我的用户控件的子项。
我只是在努力实现如何将按下的按钮传递给我的 DialogService.cs
项目结构
MainWindowViewModel.cs
视图模型非常简单。它继承自实现 ViewModelBase
的 INotifyPropertyChanged
。我也在使用基本的 RelayCommand
实现。当按下其中一个按钮时,我会调用我的 CustomDialogService
。
public class MainWindowViewModel : ViewModelBase
{
private string _text = "This is my MainWindowViewModel";
public string Text
{
get { return _text; }
set
{
_text = value;
OnPropertyChanged();
}
}
public ICommand OpenDefaultCommand { get; set; }
public ICommand OpenCustomCommand { get; set; }
ICustomDialogService _customDialogService;
public MainWindowViewModel(ICustomDialogService customDialogService)
{
OpenDefaultCommand = new RelayCommand(OpenDefault,CanOpen);
OpenCustomCommand = new RelayCommand(OpenCustom,CanOpen);
_customDialogService = customDialogService;
}
// Uses default message box
private void OpenDefault(object obj)
{
var result = _customDialogService.ShowOKDialogDefault("My title","My message");
if (result == CustomDialogResult.OK)
Text = "Default OK was clicked";
else
Text = "Default Cancel was clicked";
}
// Uses custom user control
private void OpenCustom(object obj)
{
var result = _customDialogService.ShowOKDialogCustom("My title","My message");
if (result == CustomDialogResult.OK)
Text = "Custom OK was clicked";
else
Text = "Custom Cancel was clicked";
}
private bool CanOpen(object arg)
{
return true;
}
}
CustomDialogService.cs
这是我在从 CustomDialogUserControl
按下哪个按钮获取结果时遇到问题的地方。在使用内置 ShowOKDialogDefault
的 MessageBox
中,一切都很好。
public enum CustomDialogResult
{
OK,Yes,No,Cancel
}
public class CustomDialogService : ICustomDialogService
{
public CustomDialogResult ShowOKDialogDefault(string title,string message)
{
// Uses default MessageBox
var result = MessageBox.Show(message,title,MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
return CustomDialogResult.OK;
else
return CustomDialogResult.Cancel;
}
public CustomDialogResult ShowOKDialogCustom(string title,string message)
{
// Uses custom user control
var customDialog = new CustomDialogUserControl(title,message);
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Add(customDialog);
// --- THE ISSUE ---
// How do I return the result here telling me which button was pressed in my User Control?
return CustomDialogResult.Cancel;
}
// TODO: Implement other dialogs
public CustomDialogResult ShowYesNoDialog(string title,string message)
{
return CustomDialogResult.Cancel;
}
}
CustomDialogUserControl.xaml.cs
这是我的自定义用户控件。我正在尝试遵循 MVVM 并且我读到使用用户控件背后的代码是可以接受的。我正在使用依赖属性来绑定 Title
和 Message
。问题是,我有按钮的点击事件,但老实说我不知道如何将结果返回给我的 CustomDialogService
public partial class CustomDialogUserControl : UserControl
{
public CustomDialogUserControl(string title,string message)
{
InitializeComponent();
Title = title;
Message = message;
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty,value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title",typeof(string),typeof(CustomDialogUserControl));
public string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty,value); }
}
public static readonly DependencyProperty MessageProperty =
DependencyProperty.Register("Message",typeof(CustomDialogUserControl));
private void OK_Click(object sender,RoutedEventArgs e)
{
// My issue
var result = CustomDialogResult.OK;
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Remove(this);
}
private void Cancel_Click(object sender,RoutedEventArgs e)
{
// My issue
var result = CustomDialogResult.Cancel;
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Remove(this);
}
任何帮助将不胜感激。感觉解决方案很简单,但我已经花了很多时间在这上面,我想我会向社区寻求帮助。
如果我的代码中还有什么突出的地方打破了 MVVM 模式,请告诉我。
根据用户 2250152 的回复更新
感谢您的回复 - 我自己尝试过这种方法,但是当我打开对话框时,Text
中的 MainWindowViewModel
属性在我按下任何按钮之前更改为 OK。请参阅下面的快照:
这些是我根据回复对代码所做的更改以供将来参考:
CustomDialogUserControl.xaml.cs
public CustomDialogResult Result { get; set; }
private void OK_Click(object sender,RoutedEventArgs e)
{
// My issue
Result = CustomDialogResult.OK;
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Remove(this);
}
private void Cancel_Click(object sender,RoutedEventArgs e)
{
// My issue
Result = CustomDialogResult.Cancel;
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Remove(this);
}
CustomDialogService.cs
public CustomDialogResult ShowOKDialogCustom(string title,message);
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Add(customDialog);
return customDialog.Result;
}
解决方法
我将在 Result
中创建类型为 CustomDialogResult
的新属性 CustomDialogUserControl.xaml.cs
,并将结果分配到 OK_Click
和 Cancel_Click
。
public CustomDialogResult Result { get; set; }
...
private void OK_Click(object sender,RoutedEventArgs e)
{
Result = CustomDialogResult.OK;
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Remove(this);
}
private void Cancel_Click(object sender,RoutedEventArgs e)
{
Result = CustomDialogResult.Cancel;
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Remove(this);
}
读取CustomDialogService.cs
中的结果
public CustomDialogResult ShowOKDialogCustom(string title,string message)
{
// Uses custom user control
var customDialog = new CustomDialogUserControl(title,message);
((MainWindow)System.Windows.Application.Current.MainWindow).MainGrid.Children.Add(customDialog);
return customDialog.Result;
}
,
向您的 Result
类添加一个 CustomDialogUserControl.xaml.cs
属性,并根据您的更新在按钮的 Click
事件处理程序中设置该属性。
我自己尝试过这种方法,但是当我打开对话框时,MainWindowViewModel 中的 Text 属性在我按下任何按钮之前更改为 OK。
由于 Result
的默认值是 CustomDialogResult.OK
,或者无论调用 enum
的第一个选项,您应该将属性的类型更改为 Nullable<Result>
(Result?
) 或将 Undefined
选项添加到 enum
。
然后您可以根据属性的值正确设置 Text
属性,例如:
private void OpenDefault(object obj)
{
var result = _customDialogService.ShowOKDialogDefault("My title","My message");
Text = string.Empty;
if (result.HasValue)
{
if (result.Value == CustomDialogResult.OK)
Text = "Default OK was clicked";
else
Text = "Default Cancel was clicked";
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。