Dimensione del tempo di progettazione di UserControl WPF

Quando creo un UserControl in WPF, trovo conveniente dargli alcuni valori di altezza e larghezza arbitrari in modo che possa visualizzare le mie modifiche nel designer di Visual Studio. Quando eseguo il controllo, tuttavia, voglio che Altezza e Larghezza non siano definiti, in modo che il controllo si espanda per riempire qualsiasi contenitore in cui lo inserisco. Come posso ottenere questa stessa funzionalità senza dover rimuovere i valori di Altezza e Larghezza prima costruendo il mio controllo? (O senza usare DockPanel nel contenitore genitore.)

Il seguente codice dimostra il problema:

     

La seguente definizione di UserControl1 viene visualizzata in modo ragionevole in fase di progettazione ma viene visualizzata come dimensione fissa in fase di esecuzione:

    

La seguente definizione di UserControl1 viene visualizzata come un punto in fase di progettazione ma si espande per riempire la Window1 in fase di esecuzione:

    

In Visual Studio aggiungi l’attributo Larghezza e Altezza al tuo XAML UserControl, ma nel code-behind inserisci questo

 public UserControl1() { InitializeComponent(); if (LicenseManager.UsageMode != LicenseUsageMode.Designtime) { this.Width = double.NaN; ; this.Height = double.NaN; ; } } 

Questo controlla se il controllo è in esecuzione in modalità Progettazione. In caso contrario (es. Runtime) imposterà la larghezza e l’altezza in NaN (non un numero) che è il valore in cui viene impostato se si rimuovono gli attributi di larghezza e altezza in XAML.

Quindi in fase di progettazione si avrà la larghezza e l’altezza preimpostate (incluso se si mette il controllo utente in una forma) e in fase di runtime si ancorerà a seconda del suo contenitore principale.

Spero possa aiutare.

Per Blend, un trucco poco noto è aggiungere questi attributi al tuo usercontrol o finestra:

  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="600" 

Questo imposterà l’altezza e la larghezza del disegno rispettivamente a 500 e 600. Tuttavia questo funzionerà solo per il designer di blend. Non è il Visual Studio Designer.

Per quanto riguarda Visual Studio Designer, la tua tecnica è tutto ciò che funziona. Per questo motivo non utilizzo Visual Studio Designer. 😉

Ecco una lista di attributi in fase di progettazione in Silverlight Designer . Sono gli stessi per il designer WPF.

Elenca tutti i valori d: disponibili in Designer come d:DesignHeight , d:DesignWidth , d:IsDesignTimeCreatable , d:CreateList e molti altri.

Lo faccio sempre. È sufficiente impostare i valori di larghezza e altezza su “auto” in cui viene istanziato il controllo e questo sostituirà i valori in fase di progettazione per tale UserControl.

es .:

Un’altra opzione è impostare una combinazione di MinWidth e MinHeight con una dimensione che consenta il lavoro in fase di progettazione, mentre Width e Height restano “auto”. Ovviamente, questo funziona solo se non è necessario che UserControl riduca dimensioni inferiori ai valori minimi in fase di esecuzione.

Stavo cercando una soluzione simile a quella usata in Blend e con le tue citazioni ho creato una class di comportamento semplice con due proprietà associate Width & Height che sono applicate solo in DesinTime

 class statica pubblica DesignBehavior 
 {
     private static readonly Tipo OwnerType = typeof (DesignBehavior);

     #regione larghezza

     public static readonly DependencyProperty WidthProperty =
         DependencyProperty.RegisterAttached (
             "Larghezza",
             tipo di (doppio),
             OwnerType,
             new FrameworkPropertyMetadata (double.NaN, new PropertyChangedCallback (WidthChangedCallback)));

     Double GetWidth statico pubblico (DepOpzioneOggetto depObj)
     {
         return (double) depObj.GetValue (WidthProperty);
     }

     pubblico static void SetWidth (DependencyObject depObj, double value)
     {
         depObj.SetValue (WidthProperty, value);
     }

     static static void WidthChangedCallback (DependencyObject depObj, DependencyPropertyChangedEventArgs e)
     {
         if (DesignerProperties.GetIsInDesignMode (depObj)) {
             depObj.SetValue (FrameworkElement.WidthProperty, e.NewValue);
         }
     }

     #endregion

     #regione altezza

     public static readonly DependencyProperty HeightProperty =
         DependencyProperty.RegisterAttached (
             "Altezza",
             tipo di (doppio),
             OwnerType,
             new FrameworkPropertyMetadata (double.NaN, new PropertyChangedCallback (HeightChangedCallback)));

     pubblico statico doppio GetHeight (DependencyObject depObj)
     {
         return (double) depObj.GetValue (HeightProperty);
     }

     pubblico static void SetHeight (DependencyObject depObj, double value)
     {
         depObj.SetValue (HeightProperty, value);
     }


     static static void HeightChangedCallback (DependencyObject depObj, DependencyPropertyChangedEventArgs e)
     {
         if (DesignerProperties.GetIsInDesignMode (depObj)) {
             depObj.SetValue (FrameworkElement.HeightProperty, e.NewValue);
         }
     }

     #endregion

 }

Quindi nel tuo UserControl hai appena impostato queste proprietà in Xaml

 
     
          ...
     
 

Utilizzare MinWidth e MinHeight sul controllo. In questo modo, lo vedrai nel designer e in fase di runtime si ridimensionerà nel modo desiderato.

Lo faccio in modo simile, ma la mia soluzione assicura che se si aggiunge il controllo a un contenitore in modalità progettazione, apparirà ragionevolmente.

 protected override void OnVisualParentChanged(DependencyObject oldParent) { if (this.Parent != null) { this.Width = double.NaN; this.Height = double.NaN; } } 

cosa ne pensi?

Grazie al risponditore originale per questa soluzione! Per quelli che sono interessati, eccolo in VB:

 If LicenseManager.UsageMode <> LicenseUsageMode.Designtime Then Me.Width = Double.NaN Me.Height = Double.NaN End If 

Alcuni hanno suggerito di usare la proprietà LicenseManager.UsageMode che non ho mai visto prima ma ho usato il seguente codice.

 if(!DesignerProperties.GetIsInDesignMode(this)) { this.Width = double.NaN; this.Height = double.NaN; } 

esskar,

Voglio solo aggiungere che in genere si dovrebbe sempre chiamare il metodo della base quando si sovrascrive un metodo “On”.

 protected override void OnVisualParentChanged(DependencyObject oldParent) { base.OnVisualParentChanged(oldParent); ... } 

A proposito, la soluzione è ottima, lo sto usando anch’io da solo.