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

下面的定义 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>
有帮助吗?

解决方案

在 Visual Studio 中,将 Width 和 Height 属性添加到 UserControl XAML 中,但在代码隐藏中插入此属性

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

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

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

希望有帮助。

其他提示

对于 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。;)

这里有一个列表 Silverlight 设计器中的设计时属性. 。对于 WPF 设计器来说它们是相同的。

它列出了所有 d: 设计器中可用的值,例如 d:DesignHeight, d:DesignWidth, d:IsDesignTimeCreatable, d:CreateList 和其他几个。

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

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

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

我一直在寻找类似的解决方案,例如 Blend 中使用的解决方案,根据您的提及,我创建了简单的行为类,其中包含两个附加属性“宽度”和“高度”,仅在 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>

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

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

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

你怎么认为?

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

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

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

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

埃斯卡,

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

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

    ...
}

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top