我想更改 MahApps.Metro 对话框的基本模板(或创建新的对话框类型),因为我想在狭窄的登录窗口中显示它们。现在几乎消息中的所有第二个单词都在一个新行中,但右侧和左侧有很大的空格,我想减少。
我在page_cache_alloc_cold
中发现消息对话框垂直分为三个部分:左侧 25%空间, 50%右侧的内容和 25%空间。我想改变这些数字。
但是如何用新的控件模板更改BaseMetroDialog.xaml
的控件模板?
答案 0 :(得分:25)
只需创建自己的样式即可覆盖对话框Template
(并添加DialogShownStoryboard
)。
<Style TargetType="{x:Type Dialog:BaseMetroDialog}"
x:Key="NewCustomDialogStyle"
BasedOn="{StaticResource {x:Type Dialog:BaseMetroDialog}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Dialog:BaseMetroDialog}">
<ControlTemplate.Resources>
<Storyboard x:Key="DialogShownStoryboard">
<DoubleAnimation AccelerationRatio=".9"
BeginTime="0:0:0"
Duration="0:0:0.2"
Storyboard.TargetProperty="Opacity"
To="1" />
</Storyboard>
</ControlTemplate.Resources>
<Grid Background="{TemplateBinding Background}">
<Border FocusVisualStyle="{x:Null}"
Focusable="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0"
Content="{TemplateBinding DialogTop}" />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="80*" />
<ColumnDefinition Width="10*" />
</Grid.ColumnDefinitions>
<!-- Content area -->
<Grid Grid.Column="1"
Margin="0 10 0 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
FontSize="{DynamicResource DialogTitleFontSize}"
Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Title}"
TextWrapping="Wrap" />
<ContentPresenter Grid.Row="1"
Content="{TemplateBinding Content}" />
</Grid>
</Grid>
<ContentPresenter Grid.Row="2"
Content="{TemplateBinding DialogBottom}" />
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource DialogShownStoryboard}" />
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这里的命名空间是
xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
现在使用此自定义样式,例如用于自定义对话框
<Dialog:CustomDialog x:Key="CustomDialogTest"
Style="{StaticResource NewCustomDialogStyle}"
Title="This dialog allows arbitrary content. It will close in 5 seconds."
x:Name="CustomTestDialog">
<StackPanel>
<TextBlock Height="30"
Text="This dialog allows arbitrary content. You have to close it yourself by clicking the close button below."
TextWrapping="Wrap"
Foreground="{DynamicResource AccentColorBrush}" />
<Button Content="Close Me!" />
</StackPanel>
</Dialog:CustomDialog>
主演示
的屏幕截图
<强>更新强>
使用最新版本的MahApps.Metro现在可以更改,例如全局MessageDialog
样式。
<Style TargetType="{x:Type Dialog:MessageDialog}"
x:Key="NewCustomMessageDialogStyle"
BasedOn="{StaticResource {x:Type Dialog:BaseMetroDialog}}">
<Setter Property="Template">
<!-- the custom template for e.g. MessageDialog -->
</Setter>
</Style>
<Style TargetType="{x:Type Dialog:MessageDialog}" BasedOn="{StaticResource NewCustomMessageDialogStyle}" />
希望有所帮助!
答案 1 :(得分:3)
我花了一些时间来解决这个问题,但对于像我这样的新手来说,这是我完全记录的使用mahapps和MVVM创建自定义对话框的解决方案。 可能有些方面可以改进,但这对我有用。
在App.xaml中声明对话框资源字典,以便全局可用
<Application x:Class="MyAppName.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyAppName"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<ResourceDictionary Source="DialogResource.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
资源字典包含自定义对话框的模板替换代码
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyAppName.MyResources"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
>
<!== Override default template for Mahapps custom dialog -->
<Style TargetType="{x:Type Dialog:BaseMetroDialog}"
x:Key="NewCustomDialogStyle"
BasedOn="{StaticResource {x:Type Dialog:BaseMetroDialog}}">
<Setter Property="Template">
<!-- Custom template xaml code goes here -- see above StackOverflow answer from Punker76 --->
</Setter>
</Style>
</ResourceDictionary>
创建一个名为UserInputDialog的WPF窗口,然后用customdialog xaml替换所有 xaml代码。 我使用Caliburn Micro语法将按钮绑定到底层对话框viewmodel(cal:Message.Attach =)。 在对话框xaml代码的情况下,我需要手动指定按钮绑定,因为Caliburn Micro的某些原因它不像主视图模型那样是自动的。
<Dialog:CustomDialog
x:Name="MyUserInputDialog"
x:Class="MyAppName.UserInputDialog"
Style="{StaticResource NewCustomDialogStyle}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:cal="http://www.caliburnproject.org"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
>
<!-- , diag:PresentationTraceSources.TraceLevel=High -->
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" >
<Label HorizontalAlignment="Center" Margin="10" Content="{Binding MessageText}" />
<TextBox x:Name="tbInput"
Width="200"
Margin="10"
Content="{Binding UserInput}"
HorizontalAlignment="Center"
KeyDown="tbInput_KeyDown"
/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10,20" >
<Button x:Name="butOK"
Content="OK"
Width="80"
Margin="10,0"
HorizontalAlignment="Center"
cal:Message.Attach="butOK"
/>
<Button x:Name="butCancel"
Content="Cancel"
Width="80"
Margin="10,0"
HorizontalAlignment="Center"
cal:Message.Attach="butCancel"
/>
</StackPanel>
</StackPanel>
</Dialog:CustomDialog>
UserInputDialog的代码隐藏:
using MahApps.Metro.Controls.Dialogs;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace MyAppName
{
public partial class UserInputDialog : CustomDialog
{
public UserInputDialog()
{
InitializeComponent();
MinWidth = 300;
MinHeight = 300;
Loaded += Dialog_Loaded;
}
private void Dialog_Loaded(Object sender, RoutedEventArgs e)
{
tbInput.Focus();
}
private void tbInput_KeyDown(object sender, KeyEventArgs e)
{
//Not strictly MVVM but prefer the simplicity of using code-behind for this
switch (e.Key)
{
case Key.Enter:
if(this.DataContext != null) (dynamic)this.DataContext.butOK();
break;
case Key.Escape:
if(this.DataContext != null) (dynamic)this.DataContext.butCancel();
break;
}
}
}
}
专门为用户输入对话框创建viewmodel类
using System;
using System.Windows.Input;
using Caliburn.Micro;
using MyAppName.Models;
using System.Security;
namespace MyAppName.ViewModels
{
public class UserInputViewModel : PropertyChangedBase
{
private readonly ICommand _closeCommand;
public string MessageText { get; set; } // Message displayed to user
public string UserInput { get; set; } // User input returned
public bool Cancel { get; set; } // Flagged true if user clicks cancel button
//Constructor
public UserInputViewModel(Action<UserInputViewModel> closeHandler)
{
Cancel = false;
_closeCommand = new SimpleCommand { ExecuteDelegate = o => closeHandler(this) };
}
public void butCancel()
{
Cancel = true;
_closeCommand.Execute(this);
}
public void butOK()
{
Cancel = false;
_closeCommand.Execute(this);
}
//-----------------
}
}
创建一个单独的ICommand类,通过对话框viewmodel构造函数传递外部对话框关闭函数
using System;
using System.Windows.Input;
namespace MyAppName.Models
{
public class SimpleCommand : ICommand
{
public Predicate<object> CanExecuteDelegate { get; set; }
public Action<object> ExecuteDelegate { get; set; }
public bool CanExecute(object parameter)
{
if (CanExecuteDelegate != null)
return CanExecuteDelegate(parameter);
return true; // if there is no can execute default to true
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
if (ExecuteDelegate != null)
ExecuteDelegate(parameter);
}
}
}
最后,这里是主视图模型代码,用于显示自定义对话框并处理返回的用户输入: -
using MahApps.Metro.Controls.Dialogs;
namespace MyAppName.ViewModels
{
/// <summary>
/// The ViewModel for the application's main window.
/// </summary>
public class MainViewModel : PropertyChangedBase
{
private readonly IDialogCoordinator _dialogCoordinator;
//Constructor
public MainViewModel(IDialogCoordinator dialogCoordinator)
{
// Dialog coordinator provided by Mahapps framework
// Either passed into MainViewModel constructor to conform to MVVM:-
_dialogCoordinator = dialogCoordinator;
// or just initialise directly here
// _dialogCoordinator = new DialogCoordinator();
}
public async void GetUserInput()
{
var custom_dialog = new UserInputDialog();
custom_dialog.Height = 300;
custom_dialog.Width = 400;
var dialog_vm = new UserInputViewModel(async instance =>
{
await _dialogCoordinator.HideMetroDialogAsync(this, custom_dialog);
//instance --> dialog ViewModel
if (!(instance.Cancel || String.IsNullOrEmpty(instance.UserInput)) ProcessUserInput(instance.UserInput);
});
dialog_vm.MessageText = "Please type in your first name";
custom_dialog.DataContext = dialog_vm;
await _dialogCoordinator.ShowMetroDialogAsync(this, custom_dialog);
}
public ProcessUserInput(string input_message){
Console.WriteLine("Users firstname is " + input_message);
}
}
}
答案 2 :(得分:0)
覆盖metrodialog样式并将资源合并到Metro Window
<Style x:Key="newDialogStyle" BasedOn="{StaticResource MetroDialogStyle}"
TargetType="{x:Type Dialogs:BaseMetroDialog}">
<!-- ur design of Control Template -->
</Style>
<Dialogs:CustomDialog Style="{StaticResource newDialogStyle}" Title="Custom Dialog which is awaitable">
<StackPanel>
<TextBlock Height="30" Text="This dialog allows arbitrary content. You have to close it yourself by clicking the close button below."
TextWrapping="Wrap"
Foreground="{DynamicResource AccentColorBrush}" />
<Button Content="Close Me!"/>
</StackPanel>
</Dialogs:CustomDialog>
答案 3 :(得分:0)
bug tracker提供了另一种解决方案:不使用Content属性,而是使用DialogTop。例如:
<dialogs:CustomDialog.DialogTop>
<StackPanel>
....
</StackPanel>
</dialogs:CustomDialog.DialogTop>
将自定义内容(例如StackPanel)放入DialogTop中,您就完成了。