it-swarm-pt.tech

Tamanho do tempo de design do WPF UserControl

Ao criar um UserControl no WPF, acho conveniente fornecer alguns valores arbitrários de Altura e Largura para que eu possa exibir minhas alterações no designer do Visual Studio. Quando executo o controle, no entanto, quero que a Altura e a Largura sejam indefinidas, para que o controle se expanda para preencher qualquer contêiner em que o colocar. Como obter essa mesma funcionalidade sem precisar remover os valores de Altura e Largura antes construindo meu controle? (Ou sem usar o DockPanel no contêiner pai.)

O código a seguir demonstra o 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>

A seguinte definição de UserControl1 é exibido razoavelmente no tempo de design, mas é exibido como um tamanho fixo no tempo de execução:

<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>

A seguinte definição de UserControl1 é exibido como um ponto no tempo de design, mas se expande para preencher o pai Window1 em tempo de execução:

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

No Visual Studio, adicione o atributo Width e Height ao seu UserControl XAML, mas no code-behind insira este

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

Isso verifica se o controle está sendo executado no modo de design. Caso contrário (ou seja, tempo de execução), ele definirá Largura e Altura como NaN (Não é um número), que é o valor que você definirá se remover os atributos Largura e Altura no XAML.

Portanto, no tempo de design, você terá a largura e a altura predefinidas (incluindo se você colocar o controle do usuário em um formulário) e, em tempo de execução, ele será encaixado, dependendo do contêiner pai.

Espero que ajude.

38
Alex Duggleby

Para o Blend, um truque pouco conhecido é adicionar esses atributos ao seu controle ou janela do usuário:

 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"

Isso definirá a altura e a largura do projeto para 500 e 600, respectivamente. No entanto, isso funcionará apenas para o designer de mistura. Não é o Visual Studio Designer.

No Visual Studio Designer, sua técnica é tudo o que funciona. É por isso que não uso o Visual Studio Designer. ;)

79
Brian Leahy

Aqui está uma lista de Atributos em tempo de design no Silverlight Designer . Eles são os mesmos para o designer do WPF.

Ele lista todos os d: valores disponíveis no Designer, como d:DesignHeight, d:DesignWidth, d:IsDesignTimeCreatable, d:CreateList e vários outros.

8
CLaRGe

Eu faço isso toda hora. Simplesmente defina os valores de largura e altura como "automático", onde você instancia seu controle, e isso substituirá os valores em tempo de design para esse UserControl.

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

Outra opção é definir uma combinação de MinWidth e MinHeight para um tamanho que permita trabalho em tempo de design, enquanto Largura e Altura permanecem "automáticas". Obviamente, isso só funciona se você não precisar que o UserControl tenha um tamanho menor que os valores mínimos no tempo de execução.

6
AndyL

Eu estava procurando por uma solução semelhante como a usada no Blend e, com suas menções, criei uma classe de comportamento simples com duas propriedades anexas Width & Height que são aplicadas apenas no DesinTime

 classe estática pública 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))); 
 
 público estático duplo GetWidth (DependencyObject depObj) 
 {
 return (double) depObj. GetValue (WidthProperty); 
} 
 
 Public static void SetWidth (DependencyObject depObj, valor duplo) 
 {
 DepObj.SetValue (WidthProperty, valor ); 
} 
 
 private static 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)))); 
 
 público estático duplo GetHeight (DependencyObject depObj) 
 {
 return (double) depObj.GetValue (HeightProperty); 
} 
 
 public static void SetHeight (DependencyObject depObj, valor duplo ) 
 {
 depObj.SetValue (HeightProperty, value); 
} 
 
 
 private static void HeightChangedCallback (DependencyObject depObj, DependencyPropertyChangedEven tArgs e) 
 {
 if (DesignerProperties.GetIsInDesignMode (depObj)) {
 depObj.SetValue (FrameworkElement.HeightProperty, e.NewValue); 
} 
} 
 
 # região 
 
} 

Então, no UserControl, você apenas define essas propriedades no 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 e MinHeight no controle. Dessa forma, você o verá no designer e, em tempo de execução, será dimensionado da maneira que desejar.

1
Roger Dufresne

Alguns sugeriram o uso da propriedade LicenseManager.UsageMode que nunca vi antes, mas usei o código a seguir.

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

esskar,

Eu só quero acrescentar que você geralmente sempre deve chamar o método da base ao substituir um método "On".

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

    ...
}

Ótima solução alternativa, a propósito, também estou usando agora.

0
jpierson

Faço o mesmo, mas minha solução garante que, se você adicionar seu controle a um contêiner no modo de design, ele aparecerá razoavelmente.

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

o que você acha?

0
esskar

Obrigado ao responsável pela resposta original por esta solução! Para quem estiver interessado, aqui está o VB:

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