MahApps.Metroダイアログのベーステンプレートを変更したい(または新しいダイアログタイプを作成したい)。狭いログインウィンドウ。現在、メッセージの2番目の単語のほとんどすべてが新しい行にありますが、右側と左側にニースの大きなスペースがあります。これを減らしたいと思います。
BaseMetroDialog.xaml
で、メッセージダイアログが垂直方向に3つの部分に分割されていることがわかりました:25%左側のスペース、50%コンテンツと右側の25%スペース。これらの数値を変更したいと思います。
しかし、BaseMetroWindow
のコントロールテンプレートを新しいテンプレートでどのように変更できますか?
ダイアログ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}" />
お役に立てば幸いです。
これを解決するには少し時間がかかりましたが、私のような仲間の初心者のために、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ウィンドウを作成し、次にall xamlコードをcustomdialog xamlに置き換えます。 Caliburn Micro構文を使用してボタンをアンダーレイダイアログビューモデル(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クラスを作成して、ダイアログビューモデルコンストラクターを介して外部ダイアログクローズ関数に渡します
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);
}
}
}
Metrodialogスタイルをオーバーライドし、リソースをMetroウィンドウにマージします
<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>
別のソリューションが バグトラッカー で提供されています。Contentプロパティを使用せず、代わりにDialogTopを使用してください。例えば:
<dialogs:CustomDialog.DialogTop>
<StackPanel>
....
</StackPanel>
</dialogs:CustomDialog.DialogTop>
カスタムコンテンツ(StackPanelなど)をDialogTop内に配置すれば完了です。