WPF UserControl 设计时间大小

发布于 2024-07-04 03:50:31 字数 1350 浏览 10 评论 0原文

在 WPF 中创建 UserControl 时,我发现给它一些任意的高度和宽度值很方便,以便我可以在 Visual Studio 设计器中查看我的更改。 但是,当我运行该控件时,我希望高度和宽度未定义,以便控件将展开以填充我放置它的任何容器。如何实现相同的功能,而不必先删除高度和宽度值建立我的控制权? (或者不在父容器中使用 DockPanel。)

以下代码演示了该问题:

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

UserControl1 的以下定义在设计时合理显示,但在运行时显示为固定大小:

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

< code>UserControl1 在设计时显示为点,但在运行时扩展以填充父 Window1

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

When creating a UserControl in WPF, I find it convenient to give it some arbitrary Height and Width values so that I can view my changes in the Visual Studio designer. When I run the control, however, I want the Height and Width to be undefined, so that the control will expand to fill whatever container I place it in. How can I acheive this same functionality without having to remove the Height and Width values before building my control? (Or without using DockPanel in the parent container.)

The following code demonstrates the 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>

The following definition of UserControl1 displays reasonably at design time but displays as a fixed size at run time:

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

The following definition of UserControl1 displays as a dot at design time but expands to fill the parent Window1 at run time:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

林空鹿饮溪 2024-07-11 03:50:31

在控件上使用 MinWidth 和 MinHeight。 这样,您将在设计器中看到它,并且在运行时它将按照您想要的方式调整大小。

Use MinWidth and MinHeight on the control. That way, you'll see it in the designer, and at runtime it will size the way you want.

稚然 2024-07-11 03:50:31

有些人建议使用我以前从未见过的 LicenseManager.UsageMode 属性,但我使用了以下代码。

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

esskar,

我只是想补充一点,在重写“On”方法时,通常应该始终调用基础方法。

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

    ...
}

顺便说一下,这是一个很好的解决方法,我自己现在也在使用它。

Some have suggested using the LicenseManager.UsageMode property which I've never seen before but I have used the following code.

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

esskar,

I just want to add that you should generally always call the method of the base when overriding an "On" method.

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

    ...
}

Great workaround by the way, I'm using it myself now too.

挽清梦 2024-07-11 03:50:31

感谢原回答者提供的解决方案! 对于那些有兴趣的人,这里是 VB 版本:

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

Thanks to the original answerer for this solution! For those that are interested, here it is in VB:

If LicenseManager.UsageMode <> LicenseUsageMode.Designtime Then
    Me.Width = Double.NaN
    Me.Height = Double.NaN
End If
晨光如昨 2024-07-11 03:50:31

对于 Blend,一个鲜为人知的技巧是将这些属性添加到用户控件或窗口中:

 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"

这会将设计高度和宽度分别设置为 500 和 600。 然而,这仅适用于混合设计师。 不是 Visual Studio 设计器。

就 Visual Studio Designer 而言,您的技术就是有效的。 这就是为什么我不使用 Visual Studio Designer。 ;)

For Blend, a little known trick is to add these attributes to your usercontrol or window:

 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"

This will set the design height and width to 500 and 600 respectively. However this will only work for the blend designer. Not the Visual Studio Designer.

As far as the Visual Studio Designer your technique is all that works. Which is why I don't use the Visual Studio Designer. ;)

审判长 2024-07-11 03:50:31

在 Visual Studio 中,将宽度和高度属性添加到 UserControl XAML,但在代码隐藏中插入此属性。

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

这将检查控件是否在设计模式下运行。 如果不是(即运行时),它将把宽度和高度设置为 NaN(不是数字),这是您在 XAML 中删除宽度和高度属性时设置的值。

因此,在设计时,您将拥有预设的宽度和高度(包括如果您将用户控件放入表单中),并且在运行时它将根据其父容器进行停靠。

希望有帮助。

In Visual Studio add the Width and Height attribute to your UserControl XAML, but in the code-behind insert this

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

This checks to see if the control is running in Design-mode. If not (i.e. runtime) it will set the Width and Height to NaN (Not a number) which is the value you set it to if you remove the Width and Height attributes in XAML.

So at design-time you will have the preset width and height (including if you put the user control in a form) and at runtime it will dock depending on its parent container.

Hope that helps.

不必在意 2024-07-11 03:50:31

以下是设计时属性的列表Silverlight 设计器。 对于 WPF 设计器来说它们是相同的。

它列出了设计器中可用的所有 d: 值,例如 d:DesignHeightd:DesignWidthd:IsDesignTimeCreatable< /code>、d:CreateList 以及其他几个。

Here are a list of Design-Time Attributes in the Silverlight Designer. They are the same for the WPF designer.

It lists all of the d: values available in the Designer such as d:DesignHeight, d:DesignWidth, d:IsDesignTimeCreatable, d:CreateList and several others.

许一世地老天荒 2024-07-11 03:50:31

我一直这样做。 只需在实例化控件时将宽度和高度值设置为“auto”,这将覆盖该 UserControl 的设计时值。

即:

另一个选项是将 MinWidth 和 MinHeight 的组合设置为允许设计时工作的大小,而 Width和高度保持“自动”。 显然,只有当您不需要用户控件的大小小于运行时的最小值时,这才有效。

I do this all the time. Simply set the width and height values to "auto" where you instantiate your control, and this will override the design-time values for that UserControl.

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

Another option is to set a combination of MinWidth and MinHeight to a size that allows design-time work, while Width and Height remain "auto". Obviously, this only works if you don't need the UserControl to size smaller than the min values at runtime.

风透绣罗衣 2024-07-11 03:50:31

我一直在寻找类似的解决方案,例如 Blend 中使用的解决方案,根据您的提及,我创建了带有两个附加属性 Width 和 Width 的简单行为类。 仅在 DesinTime 中应用的高度

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

}

然后在您的 UserControl 中,您只需在 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>

I was looking for similar solution like the one used in Blend and with your mentions I created simple behavior class with two attached properties Width & Height that are applied only in DesinTime

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

}

Then in your UserControl you just set these properties in 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>
岛徒 2024-07-11 03:50:31

我这样做类似,但我的解决方案确保如果您在设计模式下将控件添加到容器中,它将合理地显示。

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

你怎么认为?

I do it similar, but my solution assures that if you add your control to an container in design mode, it will appear reasonably.

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

what do you think?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文