Out团队希望创建可重用,可管理的视图.例如,我们希望在不同的应用程序中重用CommonPromptView
(我们自己的,可自定义的对话框,我们可以隐藏"取消"按钮,设置标题,显示特定图标等).
该视图在其表面上有几个元素:TextBlocks,Buttons.我们想让它们成为一种风格.
那么,解决这个任务的最佳方法是什么?
视图可以是Window类型.
视图可以是UserControl类型.
在第一种情况下,可以通过两种方式支持样式:
元素样式引用了DynamicResources.
样式将传递给View的构造函数.
两者都不干净(在我看来).
但是如果View是UserControl,那么每次创建新app的人都必须创建一个新窗口来包含UserControl并将其绑定到DP(Style类型)正确.此外,如果UserControl拥有它自己非常方便的API(最常用操作的静态方法),对于包含UserControl的Window用户来说,这将丢失.
Update
CommonPromptView
作为UserControl实现的示例.
Code-behind
public sealed partial class CommonPromptView { private const int CloseViewTimeIntervalInMilliseconds = 120000; private DispatcherTimer timer; public static readonly DependencyProperty CommonPromptBorderStyleProperty = DependencyProperty.Register( "CommonPromptBorderStyle", typeof (Style), typeof (CommonPromptView), new PropertyMetadata(default(Style))); public Style CommonPromptBorderStyle { get { return (Style) GetValue(CommonPromptBorderStyleProperty); } set { SetValue(CommonPromptBorderStyleProperty, value); } } public static readonly DependencyProperty CommonPromptHeaderStyleProperty = DependencyProperty.Register( "CommonPromptHeaderStyle", typeof (Style), typeof (CommonPromptView), new PropertyMetadata(default(Style))); public Style CommonPromptHeaderStyle { get { return (Style) GetValue(CommonPromptHeaderStyleProperty); } set { SetValue(CommonPromptHeaderStyleProperty, value); } } public static readonly DependencyProperty CommonPromptMessageStyleProperty = DependencyProperty.Register( "CommonPromptMessageStyle", typeof (Style), typeof (CommonPromptView), new PropertyMetadata(default(Style))); public Style CommonPromptMessageStyle { get { return (Style) GetValue(CommonPromptMessageStyleProperty); } set { SetValue(CommonPromptMessageStyleProperty, value); } } public static readonly DependencyProperty CommonPromptSpitterStyleProperty = DependencyProperty.Register( "CommonPromptSpitterStyle", typeof (Style), typeof (CommonPromptView), new PropertyMetadata(default(Style))); public Style CommonPromptSpitterStyle { get { return (Style) GetValue(CommonPromptSpitterStyleProperty); } set { SetValue(CommonPromptSpitterStyleProperty, value); } } public static readonly DependencyProperty CommonPromptButtonStyleProperty = DependencyProperty.Register( "CommonPromptButtonStyle", typeof (Style), typeof (CommonPromptView), new PropertyMetadata(default(Style))); public Style CommonPromptButtonStyle { get { return (Style) GetValue(CommonPromptButtonStyleProperty); } set { SetValue(CommonPromptButtonStyleProperty, value); } } [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public CommonPromptView(object header = null, string message = "?? ????????????? ?????? ???????????", Visibility headerVisibility = Visibility.Collapsed, MessageBoxIconWPF iconType = MessageBoxIconWPF.Question, object affirmButtonContent = null, object cancelButtonContent = null, Visibility cancelButtonVisibility = Visibility.Visible, Visibility affirmButtonVisibility = Visibility.Visible) { InitializeComponent(); Header.Content = header ?? string.Empty; if (header == null) HeaderSplitter.Visibility = Visibility.Collapsed; Message.Content = message; Ok.Content = affirmButtonContent ?? "??"; Cancel.Content = cancelButtonContent ?? "??????"; Cancel.Visibility = cancelButtonVisibility; Header.Visibility = headerVisibility; Ok.Visibility = affirmButtonVisibility; BitmapImage icon = new BitmapImage(); icon.BeginInit(); icon.UriSource = new Uri(GetIconPath(iconType)); //new Uri("pack://application:,,,/ApplicationName;component/Resources/logo.png"); icon.EndInit(); Icon.Source = icon; SetTimer(); } private static string GetIconPath(MessageBoxIconWPF icon) { const string uri = "pack://application:,,,/Microtech.WPF.Common;component/"; string iconName; switch (icon) { case MessageBoxIconWPF.Error: iconName = "CustomDialogStop"; break; case MessageBoxIconWPF.Information: iconName = "CustomDialogInformation"; break; case MessageBoxIconWPF.Question: iconName = "CustomDialogQuestion"; break; case MessageBoxIconWPF.Warning: iconName = "CustomDialogWarning"; break; default: throw new ArgumentException("There were no such an image"); } return uri + string.Format("Images/{0}.{1}", iconName, "png"); } public CommonPromptView(string content, Visibility cancelButtonVisibility = Visibility.Visible) : this(message: content, cancelButtonVisibility: cancelButtonVisibility) { } private void SetTimer() { TimeSpan timerInterval = TimeSpan.FromMilliseconds(CloseViewTimeIntervalInMilliseconds); timer = new DispatcherTimer(timerInterval, DispatcherPriority.ApplicationIdle, (obj, e) => Cancel_Click(null, null), Dispatcher.CurrentDispatcher); timer.Start(); } public CommonPromptView() { InitializeComponent(); } public static bool PromptOnUserAgreement(string header, string message, string okText = "??", string cancelText = "???") { return new CommonPromptView(header, message, Visibility.Visible, MessageBoxIconWPF.Information, okText, cancelText).ShowDialog() .GetValueOrDefault(); } public static void PromptOnWarning(string header, string message) { new CommonPromptView(header, message, headerVisibility: Visibility.Visible, iconType: MessageBoxIconWPF.Warning, cancelButtonVisibility: Visibility.Collapsed).ShowDialog(); } public static void PromptOnError(string header, string message) { new CommonPromptView(header, message, headerVisibility: Visibility.Visible, iconType: MessageBoxIconWPF.Error, cancelButtonVisibility: Visibility.Collapsed).ShowDialog(); } public static void PromptOnSuccess(string header, string message) { new CommonPromptView(header, message, headerVisibility: Visibility.Visible, iconType: MessageBoxIconWPF.Information, cancelButtonVisibility: Visibility.Collapsed).ShowDialog(); } private void Ok_Click(object sender, RoutedEventArgs e) { StopTimer(); TryCloseTheWindow(true); } private void Cancel_Click(object sender, RoutedEventArgs e) { StopTimer(); TryCloseTheWindow(false); } private void TryCloseTheWindow(bool dialogResult) { Window parentwin = GetWindow(this); if (parentwin != null) { try { parentwin.DialogResult = dialogResult; } catch (InvalidOperationException) { } parentwin.Close(); } } private void StopTimer() { if (timer != null) { timer.Stop(); timer = null; } } }
XAML