2015-06-10 18 views
10

Vorrei cambiare il modello di base delle finestre di dialogo MahApps.Metro (o creare un nuovo tipo di finestra di dialogo), perché mi piacerebbe mostrarle in una finestra di accesso stretta. In questo momento quasi tutte le seconde parole del messaggio sono in una nuova riga, ma ci sono dei bei grandi spazi a destra e a sinistra, che vorrei ridurre.Come modificare la larghezza del modello di contenuto della finestra di dialogo MahApps.Metro?

Too wide padding on the sides

ho trovato nel BaseMetroDialog.xaml che la finestra di messaggio viene diviso in tre parti: in verticale 25% spazio sul lato sinistro, 50% per il contenuto e la 25% spazio sulla lato destro. Mi piacerebbe cambiare questi numeri.

Ma come è possibile modificare il modello di controllo di BaseMetroWindow con il mio nuovo?

risposta

24

Basta creare il proprio stile che sostituisce la finestra di dialogo Template (e aggiungere la DialogShownStoryboard troppo).

<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> 

Lo spazio dei nomi qui è

xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro" 

Ora usare questo stile personalizzato per esempio per una finestra di dialogo personalizzata

<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> 

Screenshot demo principale

enter image description here

Aggiornamento

Con l'ultima versione di MahApps.Metro è ora possibile cambiare per esempio lo stile MessageDialog a livello globale.

<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}" /> 

enter image description here

Speranza che aiuta!

+0

Ah grazie, funziona! A proposito, pensi che sia possibile applicare questo stile anche per i messagedialog, che sono mostrati dalla funzione ShowMessageAsync()? – user3126075

+1

@ user3126075 sì, certo. ho aggiornato la mia risposta. – punker76

+1

Grazie ancora! Mi hai aiutato molto.Ho già ricompilato le librerie di mahapps con alcune proprietà di dipendenza che ho aggiunto nel caso in cui fosse possibile impostare quelle larghezze di colonna dal codice :) Ma questa è una soluzione molto migliore. – user3126075

0

sostituzione di stile metrodialog e unire la risorsa alla finestra della metropolitana

<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> 
+0

Ciao! Grazie per la tua risposta, ho cercato di renderlo così ma non ho potuto farlo funzionare. Ho aggiornato la mia risposta con un po 'di codice. Questo è quello che ho inserito in MetroWindow.Resources, ma non è successo niente, ha ancora quei grandi bordi ai lati. – user3126075

+0

si potrebbe cambiare come come questo ReeganLourduraj

+0

Penso che non sia il problema delle rowdefinitions, dal momento che le colonne sono troppo larghe. Il problema è che CustomDialog utilizza ancora il suo modello originale. Tra l'altro ho aggiornato la mia domanda con un'immagine che mostra il mio problema. – user3126075

1

Mi ci è voluto un po 'di tempo per risolvere questo problema, ma per altri neofiti come me, ecco la mia soluzione completamente documentata per creare finestre di dialogo personalizzate usando mahapps e MVVM. Ci sono probabilmente aspetti che potrebbero essere migliorati, ma questo è ciò che ha funzionato per me.

dichiarare il vostro dizionario risorsa finestra di dialogo nella App.xaml quindi è disponibile a livello globale

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> 

il dizionario risorse contiene il codice di sostituzione modello per la finestra di dialogo personalizzata

DialogResource .XAML

<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> 

Creare una finestra WPF chiamato UserInputDialog quindi sostituire tutto il codice XAML con customdialog XAML. Im usando la sintassi di Caliburn Micro per associare i pulsanti alla finestra di dialogo underlay viewmodel (cal: Message.Attach =). Nel caso del codice xaml per la finestra di dialogo devo specificare manualmente i collegamenti dei pulsanti poiché per qualche motivo con Caliburn Micro non è automatico come nel modello di visualizzazione principale.

UserInputDialog.xaml

<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>  

E il code-behind per UserInputDialog:

UserInputDialog.xaml.cs

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; 
     } 

    } 


    } 
    } 

Crea classe ViewModel appositamente per la finestra di dialogo input dell'utente

UserInputViewModel.cs

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); 
     } 

     //----------------- 
    } 
    } 

Creare una classe ICommand separato per passare la funzione di chiusura finestra esterna attraverso il ViewModel costruttore di dialogo

SimpleCommand.cs

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); 
     } 
    } 
    } 

Ed ecco finalmente il principale codice di vista del modello per visualizzare la finestra di dialogo personalizzate ed elaborare l'input utente restituito: -

MainViewModel.cs

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); 

     } 
    } 

    } 
+0

Hey, CustomDialog non contiene InitializeComponent(); più. Sai in qualche modo? –

0

Un'altra soluzione è disponibile su bug tracker: non utilizzare la proprietà Contenuto, utilizzare invece il DialogTop. Per esempio:

<dialogs:CustomDialog.DialogTop> 
    <StackPanel> 
     .... 
    </StackPanel> 
</dialogs:CustomDialog.DialogTop> 

Metti la tua contenuti personalizzati (ad esempio StackPanel) all'interno DialogTop e il gioco è fatto.