Question

Lors de la création d'un UserControl dans WPF, je trouve pratique de lui attribuer des valeurs arbitraires de hauteur et de largeur afin de pouvoir afficher mes modifications dans le concepteur Visual Studio. Toutefois, lorsque j'exécute le contrôle, je souhaite que la hauteur et la largeur ne soient pas définies, afin que le contrôle se développe afin de remplir le conteneur dans lequel je le place. Comment obtenir cette même fonctionnalité sans supprimer les valeurs de hauteur et de largeur avant construire mon contrôle? (Ou sans utiliser DockPanel dans le conteneur parent.)

Le code suivant illustre le problème:

<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 définition suivante de UserControl1 s'affiche de manière raisonnable au moment de la conception, mais sous une taille fixe à l'exécution:

<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 définition suivante de Window1 s'affiche sous forme de point au moment de la conception mais s'agrandit pour remplir le parent <=> au moment de l'exécution:

<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>
Était-ce utile?

La solution

Dans Visual Studio, ajoutez les attributs Width et Height à votre UserControl XAML, mais insérez-le dans le code-behind

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

Ceci vérifie si le contrôle s'exécute en mode conception. Si ce n’est pas le cas (exécution), il définira la largeur et la hauteur sur NaN (il ne s’agit pas d’un nombre), ce qui correspond à la valeur que vous définissez si vous supprimez les attributs largeur et hauteur en XAML.

Ainsi, au moment du design, vous aurez la largeur et la hauteur prédéfinies (y compris si vous placez le contrôle utilisateur dans un formulaire). Au moment de l'exécution, il sera ancré en fonction de son conteneur parent.

L’espoir que cela aide.

Autres conseils

Pour Blend, une astuce peu connue consiste à ajouter ces attributs à votre contrôle utilisateur ou à votre fenêtre:

 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"

Ceci définira la hauteur et la largeur de conception à 500 et 600 respectivement. Cependant, cela ne fonctionnera que pour le concepteur de mélange. Pas le concepteur Visual Studio.

En ce qui concerne Visual Studio Designer, votre technique est tout ce qui fonctionne. C'est pourquoi je n'utilise pas Visual Studio Designer. ;)

Voici une liste de Design- Attributs de temps dans le concepteur Silverlight . Ce sont les mêmes pour le concepteur WPF.

Il répertorie toutes les d: valeurs disponibles dans Designer, telles que d:DesignHeight, d:DesignWidth, d:IsDesignTimeCreatable, d:CreateList et plusieurs autres.

Je le fais tout le temps. Définissez simplement les valeurs de largeur et de hauteur sur & Quot; auto & Quot; où vous instanciez votre contrôle, ce qui annulera les valeurs de conception de cet UserControl.

c'est-à-dire: <loc:UserControl1 Width="auto" Height="auto" />

Une autre option consiste à définir une combinaison de MinWidth et MinHeight sur une taille permettant le travail au moment du design, tandis que Width et Height restent & "auto &"; Bien entendu, cela ne fonctionne que si vous n’avez pas besoin que UserControl ait une taille inférieure à la valeur minimale au moment de l’exécution.

Je recherchais une solution similaire à celle utilisée dans Blend et avec vos mentions, j'ai créé une classe de comportement simple avec deux propriétés attachées Width & amp; Hauteur appliquée uniquement dans 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

}

Ensuite, dans votre contrôle utilisateur, vous venez de définir ces propriétés dans 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>

Utilisez MinWidth et MinHeight sur le contrôle. De cette façon, vous le verrez dans le concepteur et, à l'exécution, la taille sera telle que vous le souhaitez.

Je le fais de manière similaire, mais ma solution garantit que si vous ajoutez votre contrôle à un conteneur en mode conception, il apparaîtra raisonnablement.

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

qu'en pensez-vous?

Merci au répondant d'origine pour cette solution! Pour ceux qui sont intéressés, le voici en VB:

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

Certains ont suggéré d'utiliser la propriété LicenseManager.UsageMode que je n'ai jamais vue auparavant mais que j'ai utilisé le code suivant.

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

esskar,

Je veux juste ajouter que vous devez généralement toujours appeler la méthode de la base lorsque vous écrasez un & "On &"; méthode.

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

    ...
}

Excellente solution de contournement, je l'utilise moi aussi maintenant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top