it-swarm-es.tech

Tamaño de tiempo de diseño de control de usuario de WPF

Al crear un UserControl en WPF, me parece conveniente darle algunos valores arbitrarios de Altura y Ancho para que pueda ver mis cambios en el diseñador de Visual Studio. Sin embargo, cuando ejecuto el control, quiero que la Altura y el Ancho no estén definidos, de modo que el control se expanda para llenar el contenedor en el que lo coloque. ¿Cómo puedo lograr esta misma funcionalidad sin tener que eliminar los valores de Altura y Ancho antes? construyendo mi control? (O sin usar DockPanel en el contenedor principal).

El siguiente código demuestra el 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 siguiente definición de UserControl1 se muestra razonablemente en tiempo de diseño pero se muestra como un tamaño fijo en tiempo de ejecución:

<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 siguiente definición de UserControl1 se muestra como un punto en tiempo de diseño pero se expande para llenar el padre Window1 en tiempo de ejecución:

<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>
50
Joseph Sturtevant

En Visual Studio, agregue el atributo Width y Height a su UserControl XAML, pero en el código subyacente inserte esto

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

Esto verifica si el control se está ejecutando en modo Diseño. Si no es así (es decir, tiempo de ejecución) establecerá el ancho y la altura en NaN (no es un número), que es el valor que establecerá si elimina los atributos de ancho y altura en XAML.

Por lo tanto, en tiempo de diseño tendrá el ancho y la altura preestablecidos (incluso si coloca el control de usuario en un formulario) y en tiempo de ejecución se acoplará en función de su contenedor principal.

Espero que ayude.

38
Alex Duggleby

Para Blend, un truco poco conocido es agregar estos atributos a su control de usuario o ventana:

 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"

Esto establecerá la altura y el ancho del diseño en 500 y 600 respectivamente. Sin embargo, esto solo funcionará para el diseñador de mezclas. No es el diseñador de Visual Studio.

En cuanto al Visual Studio Designer, su técnica es todo lo que funciona. Es por eso que no uso Visual Studio Designer. ;)

78
Brian Leahy

Aquí hay una lista de Atributos de tiempo de diseño en Silverlight Designer . Son lo mismo para el diseñador WPF.

Enumera todos los valores de d: disponibles en el Diseñador, como d:DesignHeight, d:DesignWidth, d:IsDesignTimeCreatable, d:CreateList y varios otros.

8
CLaRGe

Hago esto todo el tiempo. Simplemente establezca los valores de ancho y alto en "auto" donde instanciará su control, y esto anulará los valores de tiempo de diseño para ese UserControl.

es decir: <loc:UserControl1 Width="auto" Height="auto" />

Otra opción es establecer una combinación de MinWidth y MinHeight en un tamaño que permita el trabajo en tiempo de diseño, mientras que Ancho y Altura permanecen "automáticos". Obviamente, esto solo funciona si no necesita UserControl para un tamaño más pequeño que los valores mínimos en tiempo de ejecución.

6
AndyL

Estaba buscando una solución similar a la utilizada en Blend y con sus menciones creé una clase de comportamiento simple con dos propiedades adjuntas Ancho y Alto que se aplican solo en DesinTime

 public static class DesignBehavior 
 {
 private static readonly Escriba OwnerType = typeof (DesignBehavior); 
 
 #region Width 
 
 público estático de solo lectura DependencyProperty WidthProperty = 
 DependencyProperty.RegisterAttached (
 "Width", 
 typeof (double), 
 OwnerType, 
 nuevo FrameworkPropertyMetadata (double.NaN, nuevo PropertyChangedCallback (WidthChangedCallback))); 
 
 público estático doble GetWidth (DependencyObject depObj) 
 {
 return (double) depObj. GetValue (WidthProperty); 
} 
 
 Público estático SetWidth (DependencyObject depObj, valor doble) 
 {
 DepObj.SetValue (WidthProperty, valor ); 
} 
 
 vacío estático privado 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 (doble) depObj.GetValue (HeightProperty); 
} 
 
 público estático vacío SetHeight (DependencyObject depObj, valor doble ) 
 {
 depObj.SetValue (HeightProperty, value); 
} 
 
 
 vacío estático privado HeightChangedCallback (DependencyObject depObj, DependenciaPropiedadCambiadoIncluso tArgs e) 
 {
 if (DesignerProperties.GetIsInDesignMode (depObj)) {
 depObj.SetValue (FrameworkElement.HeightProperty, e.NewValue); 
} 
} 
 
 #endregion 
 
} 

Luego, en su UserControl, simplemente configure estas propiedades en 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> 
2
Ondrej

Use MinWidth y MinHeight en el control. De esa manera, lo verá en el diseñador, y en el tiempo de ejecución tendrá el tamaño que desee.

1
Roger Dufresne

Algunos han sugerido usar la propiedad LicenseManager.UsageMode que nunca he visto antes pero he usado el siguiente código.

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

esskar,

Solo quiero agregar que generalmente siempre debe llamar al método de la base al anular un método "Activado".

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

    ...
}

Gran solución, por cierto, ahora también lo estoy usando.

0
jpierson

Lo hago de manera similar, pero mi solución asegura que si agrega su control a un contenedor en modo de diseño, aparecerá razonablemente.

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

¿Qué piensas?

0
esskar

¡Gracias al respondedor original por esta solución! Para aquellos que estén interesados, aquí está en VB:

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