Lors de la création d'un UserControl dans WPF, je trouve pratique de lui donner des valeurs arbitraires de hauteur et de largeur afin que je puisse voir mes modifications dans le concepteur Visual Studio. Cependant, 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 pour remplir le conteneur dans lequel je le place. Comment puis-je obtenir cette même fonctionnalité sans avoir à 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 raisonnablement au moment de la conception mais s'affiche comme une taille fixe 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"
Height="300" Width="300">
<Grid Background="LightCyan" />
</UserControl>
La définition suivante de UserControl1
s'affiche sous forme de point au moment du design mais se développe pour remplir le parent Window1
lors 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>
Dans Visual Studio, ajoutez l'attribut 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; ;
}
}
Cela vérifie si le contrôle s'exécute en mode Conception. Si ce n'est pas le cas (c'est-à-dire à l'exécution), la largeur et la hauteur seront définies sur NaN (pas un nombre), qui est la valeur à laquelle vous la définissez si vous supprimez les attributs Largeur et Hauteur dans XAML.
Ainsi, au moment de la conception, vous aurez la largeur et la hauteur prédéfinies (y compris si vous placez le contrôle utilisateur dans un formulaire) et au moment de l'exécution, il sera ancré en fonction de son conteneur parent.
J'espère que cela pourra aider.
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"
Cela 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 Visual Studio Designer.
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 Attributs au moment du design dans Silverlight Designer . Ce sont les mêmes pour le concepteur WPF.
Il répertorie tous les d:
valeurs disponibles dans le concepteur 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 "auto" où vous instanciez votre contrôle, et cela remplacera les valeurs au moment du design pour ce UserControl.
c'est à dire: <loc:UserControl1 Width="auto" Height="auto" />
Une autre option consiste à définir une combinaison de MinWidth et MinHeight à une taille qui autorise le travail au moment de la conception, tandis que la largeur et la hauteur restent "auto". Évidemment, cela ne fonctionne que si vous n'avez pas besoin de UserControl pour une taille inférieure aux valeurs min lors de l'exécution.
Je cherchais 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 Largeur et Hauteur qui ne sont appliquées que dans DesinTime
public static class DesignBehavior { private static readonly Type OwnerType = typeof (DesignBehavior); #region Width public statique en lecture seule 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 ); } privé statique void WidthChangedCallback (DependencyObject depObj, DependencyPropertyChangedEventArgs e) { if (DesignerPropertie s.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, valeur double ) { depObj.SetValue (HeightProperty, valeur); } privé statique void HeightChangedCallback (DependencyObject depObj, DependencyPropertyChangedEven tArgs e) { if (DesignerProperties.GetIsInDesignMode (depObj)) { depObj.SetValue (FrameworkElement.HeightProperty, e.NewValue); } } #endregion }
Ensuite, dans votre UserControl, 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 lors de l'exécution, il sera dimensionné comme vous le souhaitez.
Certains ont suggéré d'utiliser la propriété LicenseManager.UsageMode que je n'ai jamais vue auparavant mais 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 lors de la substitution d'une méthode "On".
protected override void OnVisualParentChanged(DependencyObject oldParent)
{
base.OnVisualParentChanged(oldParent);
...
}
Excellente solution de contournement, je l'utilise moi aussi maintenant.
Je le fais de la même façon, 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'est-ce que tu penses?
Merci au répondeur 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