WPF UserControl 设计时间大小
-
09-06-2019 - |
题
在 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);
...
}
顺便说一下,这是一个很好的解决方法,我自己现在也在使用它。