代码之家  ›  专栏  ›  技术社区  ›  Joseph Sturtevant

WPF用户控件设计时间大小

  •  50
  • Joseph Sturtevant  · 技术社区  · 17 年前

    在WPF中创建UserControl时,我发现给它一些任意的高度和宽度值很方便,这样我就可以在VisualStudio设计器中查看我所做的更改。但是,当我运行该控件时,我希望高度和宽度是未定义的,这样该控件将扩展以填充我放置它的任何容器。在构建控件之前,如何在不删除高度和宽度值的情况下实现相同的功能?(或不在父容器中使用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>
    

    以下是 用户控制1 在设计时显示为点,但会展开以填充父对象 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>
    
    9 回复  |  直到 14 年前
        1
  •  81
  •   Brian Leahy    17 年前

    对于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。但是,这仅适用于混合设计器。不是VisualStudio设计师。

    对于VisualStudio设计师来说,你的技术就是一切。这就是我不使用Visual Studio Designer的原因。;)

        2
  •  39
  •   Alex Duggleby    17 年前

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

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

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

    希望有帮助。

        3
  •  9
  •   Chris Mantle    11 年前

    Design-Time Attributes in the Silverlight Designer . 对于WPF设计器,它们是相同的。

    它列出了所有的 d: 设计器中可用的值,例如 d:DesignHeight d:DesignWidth , d:IsDesignTimeCreatable , d:CreateList

        4
  •  7
  •   AndyL    17 年前

    我总是这样做。在实例化控件时,只需将宽度和高度值设置为“自动”,这将覆盖该用户控件的设计时值。

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

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

        5
  •  2
  •   Ondrej    14 年前

    我一直在寻找类似的解决方案,就像在Blend中使用的解决方案一样,在您的提及下,我创建了带有两个附加属性Width&的简单行为类;仅在停止时应用的高度

    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>
    
        6
  •  1
  •   Roger Dufresne    13 年前

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

        7
  •  0
  •   esskar esskar    17 年前

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

    你怎么认为?

        8
  •  0
  •   Paul    17 年前

    感谢此解决方案的原始解答者!对于感兴趣的人,这里是VB:

    If LicenseManager.UsageMode <> LicenseUsageMode.Designtime Then
        Me.Width = Double.NaN
        Me.Height = Double.NaN
    End If
    
        9
  •  0
  •   jpierson    16 年前

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

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

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

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

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