Frage

Wenn ein Usercontrol in WPF zu schaffen, finde ich es bequem es einige willkürliche Werte Höhe und Breite geben, so dass ich meine Änderungen in der Visual Studio-Designer anzuzeigen. Wenn ich die Kontrolle laufen, möchte ich jedoch die Höhe und Breite nicht definiert sein, so dass die Steuerung erweitern zu füllen, was Behälter ich es an seinem Platz. Wie kann ich diese gleiche Funktionalität acheive, ohne die Werte Höhe und Breite zu entfernen, bevor Aufbau meiner Kontrolle? (Oder ohne DockPanel in den übergeordneten Container zu verwenden.)

Der folgende Code demonstriert das Problem:

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

Die folgende Definition von UserControl1 Displays angemessen zur Entwurfszeit wird jedoch als eine feste Größe zur Laufzeit:

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

Die folgende Definition von UserControl1 Displays als Punkt zur Design-Zeit, sondern erweitert die Eltern Window1 zur Laufzeit zu füllen:

<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>
War es hilfreich?

Lösung

In Visual Studio fügen Sie die Breite und Höhe Attribut zu Ihrem Usercontrol XAML, aber in der Code-behind fügen Sie diese

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

Diese überprüft, ob die Steuerung in der Entwurfs-Modus ausgeführt wird. Wenn nicht (das heißt Laufzeit), wird die Breite und Höhe auf NaN gesetzt (Keine Zahl), die den Wert Sie es auf, wenn Sie die Breite entfernen und Höhe Attribute in XAML.

So zur Entwurfszeit werden Sie die voreingestellte Breite und Höhe (einschließlich, wenn Sie die Benutzersteuerung in einer Form gebracht) und zur Laufzeit wird es auf seinem übergeordneten Container dock abhängig.

Ich hoffe, das hilft.

Andere Tipps

Für Blend, ein wenig bekannter Trick ist es, diese Attribute zu Ihrem Usercontrol oder Fenster hinzuzufügen:

 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"

Dadurch wird die Bauhöhe und -breite auf 500 und 600 jeweils eingestellt. Dies wird jedoch nur für die Mischung Designer arbeiten. Nicht die Visual Studio Designer.

Was die Visual Studio Designer Ihre Technik ist alles, das funktioniert. Welches ist, warum ich nicht die Visual Studio-Designer verwenden. ;)

Hier finden Sie eine Liste von Entwurfs- Zeitattribute in der Silverlight-Designer . Es sind die gleichen für die WPF-Designer.

Es listet alle der d: Werte in Designer wie d:DesignHeight, d:DesignWidth, d:IsDesignTimeCreatable, d:CreateList und einige andere.

Ich tue dies die ganze Zeit. Setzen Sie einfach Werte, die die Breite und Höhe auf „auto“, wo Sie Ihre Steuer instanziiert, und dies wird die Entwurfszeitwerte für diese Benutzersteuerelement außer Kraft setzen.

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

Eine weitere Möglichkeit ist eine Kombination aus MinWidth und MinHeight auf eine Größe einzustellen, die Design-Zeitarbeit ermöglicht, während Breite und Höhe bleiben „auto“. Offensichtlich funktioniert dies nur, wenn Sie die Usercontrol Größe kleiner als die Minimalwerte zur Laufzeit nicht brauchen.

Ich war auf der Suche nach ähnlicher Lösung wie die in Mischung verwendet und mit Ihrem erwähnt ich einfache Verhaltensklasse mit zwei aufgesetzten Eigenschaften Breite und Höhe erstellt, die nur in DesinTime angewandt werden

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

}

Dann in Ihrem Usercontrol Sie gerade diese Eigenschaften in XAML festlegen

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

Mit MinWidth und MinHeight auf das Steuerelement. Auf diese Weise werden Sie es im Designer sehen, und zur Laufzeit wird es eine Größe, wie Sie wollen.

Ich mache es ähnlich, aber meine Lösung stellt sicher, dass, wenn Sie Ihre Steuerung an einen Container im Design-Modus hinzufügen, es vernünftig erscheinen wird.

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

Was denken Sie?

Dank der ursprünglichen Antworter für diese Lösung! Für diejenigen, die interessiert sind, hier ist es in VB:

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

Einige haben mit der LicenseManager.UsageMode Eigenschaft vorgeschlagen, die ich noch nie zuvor gesehen habe, aber ich habe den folgenden Code verwendet wird.

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

esskar,

Ich möchte nur hinzufügen, dass Sie in der Regel immer die Methode der Basis anrufen sollte, wenn ein „On“ Methode überschrieben.

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

    ...
}

Große Abhilfe durch die Art und Weise, ich verwende es mich jetzt auch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top