【发布时间】:2021-05-31 11:22:57
【问题描述】:
问题
我正在努力将按下哪个按钮的结果从我的CustomDialogUserControl.xaml.cs 传递给我的CustomDialogService.cs。
背景
我可以通过我的CustomDialogService.cs 使用MessageBox.Show,一切都很好,看起来像这样:
我创建了自己的CustomDialogUserControl 来实现覆盖窗口,方法是在我的应用程序窗口中使用x:Name="MainGrid",并在需要对话框时以编程方式添加我的用户控件的子项。
我只是在努力实现如何将按下哪个按钮传递给我的DialogService.cs的功能
项目结构
MainWindowViewModel.cs
视图模型非常简单。它继承自实现INotifyPropertyChanged 的ViewModelBase。我也在使用基本的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 按下哪个按钮时遇到问题的地方。在使用内置MessageBox 的ShowOKDialogDefault 中,一切都很好。
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(string), 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 模式,请告诉我。
根据 user2250152 的回复更新
感谢您的回复 - 我自己尝试过这种方法,但是当我打开对话框时,MainWindowViewModel 中的 Text 属性在我按下任何按钮之前更改为 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, 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;
}
【问题讨论】:
-
MVVM 和视图模型组件中的对话框处理不能一起使用。 MVVM 要求视图模型不知道视图,这意味着它必须对视图绝对被动,这意味着视图模型不应该主动触发对话框。你甚至已经实现了一个逻辑来决定显示什么样的对话框。您甚至可以创建对话框实例来直接显示它们。这不是 MVVM。
-
您基本上只需要将自定义对话框的可见性从折叠状态切换为可见状态。相关逻辑必须在视图中。然后将命令附加到关闭或接受按钮。此命令应在作为 UserControl 的 DataContext 的视图模型中定义。
-
“我正在尝试关注 MVVM,并且我读到使用代码背后的用户控件是可以接受的。” - 绝对。那你为什么决定从视图模型而不是视图的代码隐藏中显示对话框?不要这样做。
标签: wpf mvvm dialog user-controls overlay