【发布时间】:2013-11-27 07:53:17
【问题描述】:
我想问一下使用 MVVM 模式和 MVVMLight 框架显示子窗口的最佳方式是什么。我在这个网站上阅读了几个主题,但我似乎不理解所编写的代码到底在做什么,所以请提供你的想法的详细解释。
【问题讨论】:
我想问一下使用 MVVM 模式和 MVVMLight 框架显示子窗口的最佳方式是什么。我在这个网站上阅读了几个主题,但我似乎不理解所编写的代码到底在做什么,所以请提供你的想法的详细解释。
【问题讨论】:
我使用服务来显示新窗口或新对话框。
你可以查看我的第一个版本的对话框here
最近几天我在界面中添加了更多重载
public interface IUIDialogWindowService
{
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
bool? ShowDialog(string titel, object datacontext);
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<param name="minHeigth">Minimum Height</param>
///<param name="minWidth">Minimum Width</param>
///<param name="maxHeigth">Maximum Height</param>
///<param name="maxWidth">Maximum Width</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
bool? ShowDialog(string titel, object datacontext, double minHeigth = 0, double minWidth=0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity);
/// <summary>
/// Zeigt ein Dialog an
/// </summary>
/// <param name="titel">Titel für den Dialog<</param>
/// <param name="datacontext">DataContext für den Dialog</param>
/// <param name="settings">ApplicationsSetting für Height and Width</param>
/// <param name="pathHeigthSetting">Name für Height Setting</param>
/// <param name="pathWidthSetting">Name für Width Setting</param>
/// <param name="minHeigth">Minimum Height</param>
/// <param name="minWidth">Minimum Width</param>
/// <param name="maxHeigth">Maximum Height</param>
/// <param name="maxWidth">Maximum Width</param>
/// <returns>true wenn DialogResult=true, ansonsten false</returns>
bool? ShowDialog(string titel, object datacontext, ApplicationSettingsBase settings, string pathHeigthSetting, string pathWidthSetting, double minHeigth = 0, double minWidth = 0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity);
}
///<summary>
/// Implementierung von <see cref="IUIDialogWindowService"/>
///</summary>
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IUIDialogWindowService))]
public class WpfUIDialogWindowService : IUIDialogWindowService
{
#region Implementation of IUIDialogWindowService
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
public bool? ShowDialog(string titel, object datacontext)
{
var win = new DialogWindow {Title = titel, DataContext = datacontext};
return win.ShowDialog();
}
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<param name="minHeigth">Minimum Height</param>
///<param name="minWidth">Minimum Width</param>
///<param name="maxHeigth">Maximum Height</param>
///<param name="maxWidth">Maximum Width</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
public bool? ShowDialog(string titel, object datacontext, double minHeigth = 0, double minWidth = 0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity)
{
var win = new DialogWindow { Title = titel, DataContext = datacontext };
win.MinHeight = minHeigth;
win.MinWidth = minWidth;
win.MaxHeight = maxHeigth;
win.MaxWidth = maxWidth;
return win.ShowDialog();
}
/// <summary>
/// Zeigt ein Dialog an
/// </summary>
/// <param name="titel">Titel für den Dialog<</param>
/// <param name="datacontext">DataContext für den Dialog</param>
/// <param name="settings">ApplicationsSetting für Height and Width</param>
/// <param name="pathHeigthSetting">Name für Height Setting</param>
/// <param name="pathWidthSetting">Name für Width Setting</param>
/// <param name="minHeigth">Minimum Height</param>
/// <param name="minWidth">Minimum Width</param>
/// <param name="maxHeigth">Maximum Height</param>
/// <param name="maxWidth">Maximum Width</param>
/// <returns>true wenn DialogResult=true, ansonsten false</returns>
public bool? ShowDialog(string titel, object datacontext, ApplicationSettingsBase settings, string pathHeigthSetting, string pathWidthSetting, double minHeigth = 0, double minWidth = 0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity)
{
var win = new DialogWindow { Title = titel, DataContext = datacontext };
win.MinHeight = minHeigth;
win.MinWidth = minWidth;
win.MaxHeight = maxHeigth;
win.MaxWidth = maxWidth;
try
{
if(settings != null)
{
win.SizeToContent = SizeToContent.Manual;
var height = settings[pathHeigthSetting];
var width = settings[pathWidthSetting];
BindingOperations.SetBinding(win, FrameworkElement.HeightProperty, new Binding(pathHeigthSetting) { Source = settings, Mode = BindingMode.TwoWay });
BindingOperations.SetBinding(win, FrameworkElement.WidthProperty, new Binding(pathWidthSetting) { Source = settings, Mode = BindingMode.TwoWay });
win.Height = (double)height;
win.Width = (double)width;
}
}
catch
{
win.SizeToContent = SizeToContent.WidthAndHeight;
}
return win.ShowDialog();
}
#endregion
}
为了完整起见:
<Window x:Class="DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
WindowStyle="SingleBorderWindow"
WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight"
Style="{DynamicResource {x:Type Window}}">
<ContentPresenter x:Name="DialogPresenter" Content="{Binding .}">
</ContentPresenter>
</Window>
public partial class DialogWindow : Window
{
public DialogWindow()
{
InitializeComponent();
this.DialogPresenter.DataContextChanged += DialogPresenterDataContextChanged;
}
private void DialogPresenterDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var d = e.NewValue as IDialogResultVMHelper;
if (d == null)
return;
d.RequestCloseDialog += new EventHandler<RequestCloseDialogEventArgs>(DialogResultTrueEvent).MakeWeak(eh => d.RequestCloseDialog -= eh);
}
private void DialogResultTrueEvent(object sender, RequestCloseDialogEventArgs eventargs)
{
this.DialogResult = eventargs.DialogResult;
}
}
public class RequestCloseDialogEventArgs : EventArgs
{
public RequestCloseDialogEventArgs(bool dialogresult)
{
this.DialogResult = dialogresult;
}
public bool DialogResult
{
get; set;
}
}
public interface IDialogResultVMHelper
{
event EventHandler<RequestCloseDialogEventArgs> RequestCloseDialog;
}
【讨论】:
首先是一个问题,一个反直觉的问题。打开一个新窗口的动作和MVVM有什么关系?
我个人认为根本没有任何联系。事实上,就像其他几个 UI 结构一样,它完全发生在 View 层中。还有其他几个类似的概念,
Next 以切换到下一页所有这些都是向用户显示新视图的不同方式。它们都存在于 View 层中,仅通过呈现绑定到 ViewModel 的新 UI 元素。
但是...围绕 MVVM 发展了许多模式来支持这一点。通常这是使用服务或控制器来处理视图操作,检查您选择的 MVVM 库是否支持显示新视图的方式。
最后一件事让我很困惑,当您需要执行操作和更改视图时会发生什么。通常,您会将 UI 对象(例如按钮)绑定到 ViewModel 级别的命令以执行操作,并依靠绑定来更新显示新值的 UI 控件。由于 ViewModel 不应该知道 View,因此任何更改 UI 的操作都必须单独发生在 View 中。这意味着您不能绑定到 ViewModel 命令。幸运的是,您可以在视图级别创建一个命令,委托给视图模型级别的操作并更改 UI。
(嗯...回读,不确定这是否能回答问题,但它可能有助于澄清您的想法)
【讨论】: