WPF UserControl Diseño Tiempo Tamaño


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

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>
Author: Dave Clemmer, 2008-09-16

9 answers

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

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

Esto comprueba si el control se está ejecutando en modo Diseño. Si no (es decir, tiempo de ejecución), establecerá el Ancho y el alto en NaN (No un número), que es el valor que se establece si se eliminan los atributos de Ancho y Alto en XAML.

Así que en el momento del diseño tendrá el ancho y la altura predefinidos (incluso si coloca el control de usuario en un formulario) y en tiempo de ejecución se acoplará dependiendo de su contenedor padre.

Espero que eso ayude.

 38
Author: Alex Duggleby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 18:44:07

Para la mezcla, 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 el Diseñador de Visual Studio.

En cuanto al Diseñador de Visual Studio, su técnica es todo lo que funciona. Por eso no uso el Diseñador de Visual Studio. ;)

 78
Author: Brian Leahy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 18:41:39

Aquí hay una lista de Atributos de Tiempo de diseño en el Diseñador de Silverlight. Son los mismos para el diseñador de WPF.

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

 8
Author: CLaRGe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-24 13:51:58

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

Ie: <loc:UserControl1 Width="auto" Height="auto" />

Otra opción es establecer una combinación de MinWidth y minHeight a un tamaño que permita el trabajo en tiempo de diseño, mientras que Width y Height permanecen "auto". Obviamente, esto solo funciona si no necesita que el UserControl tenga un tamaño menor que los valores mínimos en tiempo de ejecución.

 6
Author: AndyL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-17 01:57:35

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 Width & Height que se aplican solo en Desitime

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

}

A continuación, en su UserControl acaba de establecer 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
Author: Ondrej,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-06 09:18:51

Utilice MinWidth y minHeight en el control. De esa manera, lo verás en el diseñador, y en tiempo de ejecución se dimensionará de la manera que quieras.

 1
Author: Roger Dufresne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-29 01:56:16

Lo hago de manera similar, pero mi solución asegura que si agrega su control a un contenedor en modo 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
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-22 23:21:38

Gracias al responsable original de 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
Author: Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-07 19:58:31

Algunos han sugerido usar LicenseManager.UsageMode propiedad que nunca he visto antes, pero he utilizado 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 cuando anula un método "On".

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

    ...
}

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

 0
Author: jpierson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-24 16:32:05