Domanda

Quando creo un UserControl in WPF, trovo conveniente assegnargli alcuni valori arbitrari di altezza e larghezza in modo da poter visualizzare le modifiche nella finestra di progettazione di Visual Studio.Quando eseguo il controllo, tuttavia, desidero che l'altezza e la larghezza non siano definite, in modo che il controllo si espanda per riempire qualunque contenitore lo inserisco.Come posso ottenere la stessa funzionalità senza dover rimuovere i valori di altezza e larghezza prima di creare il mio controllo?(O senza utilizzare DockPanel nel contenitore principale.)

Il codice seguente illustra il problema:

<Window x:Class="ExampleApplication3.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:loc="clr-namespace:ExampleApplication3"
    Title="Example" Height="600" Width="600">
    <Grid Background="LightGray">
        <loc:UserControl1 />
    </Grid>
</Window>

La seguente definizione di UserControl1 viene visualizzato in modo ragionevole in fase di progettazione ma viene visualizzato con dimensioni fisse in fase di esecuzione:

<UserControl x:Class="ExampleApplication3.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid Background="LightCyan" />
</UserControl>

La seguente definizione di UserControl1 viene visualizzato come un punto in fase di progettazione ma si espande per riempire l'elemento principale Window1 in fase di esecuzione:

<UserControl x:Class="ExampleApplication3.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid Background="LightCyan" />
</UserControl>
È stato utile?

Soluzione

In Visual Studio aggiungi gli attributi Larghezza e Altezza al tuo UserControl XAML, ma nel code-behind inseriscilo

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

Ciò verifica se il controllo è in esecuzione in modalità progettazione.In caso contrario (ad es.runtime) imposterà Larghezza e Altezza su NaN (non un numero) che è il valore su cui lo imposti se rimuovi gli attributi Larghezza e Altezza in XAML.

Quindi in fase di progettazione avrai la larghezza e l'altezza preimpostate (anche se inserisci il controllo utente in un modulo) e in fase di esecuzione si ancorarà a seconda del contenitore principale.

Spero che aiuti.

Altri suggerimenti

Per Blend, un trucco poco conosciuto è aggiungere questi attributi al tuo controllo utente 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"

Ciò imposterà l'altezza e la larghezza del disegno rispettivamente su 500 e 600.Tuttavia questo funzionerà solo per il progettista della fusione.Non la finestra di progettazione di Visual Studio.

Per quanto riguarda Visual Studio Designer, la tua tecnica è tutto ciò che funziona.Questo è il motivo per cui non utilizzo Visual Studio Designer.;)

Ecco un elenco di Attributi in fase di progettazione in Silverlight Designer.Sono gli stessi per la finestra di progettazione WPF.

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

Lo faccio sempre.Imposta semplicemente i valori di larghezza e altezza su "auto" nel punto in cui crei un'istanza del controllo e questo sovrascriverà i valori della fase di progettazione per tale UserControl.

cioè: <loc:UserControl1 Width="auto" Height="auto" />

Un'altra opzione consiste nell'impostare una combinazione di MinWidth e MinHeight su una dimensione che consenta il lavoro in fase di progettazione, mentre Larghezza e Altezza rimangono "automatiche".Ovviamente, funziona solo se non è necessario che UserControl riduca le dimensioni inferiori ai valori minimi in fase di esecuzione.

Stavo cercando una soluzione simile come quella usata in Blend e con le tue menzioni ho creato una semplice classe di comportamento con due proprietà allegate Larghezza e Altezza che vengono applicate solo in DesinTime

public static class DesignBehavior 
{
    private static readonly Type OwnerType = typeof (DesignBehavior);

    #region Width

    public static readonly DependencyProperty WidthProperty =
        DependencyProperty.RegisterAttached(
            "Width",
            typeof (double),
            OwnerType,
            new FrameworkPropertyMetadata(double.NaN, new PropertyChangedCallback(WidthChangedCallback)));

    public static double GetWidth(DependencyObject depObj)
    {
        return (double)depObj.GetValue(WidthProperty);
    }

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

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

    #endregion

    #region Height

    public static readonly DependencyProperty HeightProperty =
        DependencyProperty.RegisterAttached(
            "Height",
            typeof (double),
            OwnerType,
            new FrameworkPropertyMetadata(double.NaN, new PropertyChangedCallback(HeightChangedCallback)));

    public static double GetHeight(DependencyObject depObj)
    {
        return (double)depObj.GetValue(HeightProperty);
    }

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


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

    #endregion

}

Quindi nel tuo UserControl imposti semplicemente queste proprietà in Xaml

<UserControl x:Class="ExtendedDataGrid.Views.PersonOverviewView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:tool="http://schemas.microsoft.com/wpf/2008/toolkit"
    xmlns:b="clr-namespace:ExtendedDataGrid.Behaviors"
    b:DesignBehavior.Width="600" b:DesignBehavior.Height="200">
    <Grid>
         ...
    </Grid>
</UserControl>

Utilizzare MinWidth e MinHeight sul controllo.In questo modo, lo vedrai nel designer e in fase di esecuzione verrà dimensionato nel modo desiderato.

Lo faccio in modo simile, ma la mia soluzione assicura che se aggiungi il tuo controllo a un contenitore in modalità progettazione, apparirà in modo ragionevole.

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 coloro 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 utilizzare la proprietà LicenseManager.UsageMode che non avevo mai visto prima, ma ho utilizzato il seguente codice.

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

Eskar,

Voglio solo aggiungere che generalmente dovresti sempre chiamare il metodo della base quando sovrascrivi un metodo "On".

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

    ...
}

Ottima soluzione comunque, la sto usando anch'io adesso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top