在WPF中创建UserControl时,我发现为它提供一些任意的Height和Width值很方便,这样我就可以在Visual Studio设计器中查看更改。 但是,当我运行控件时,我希望未定义Height和Width,以便控件可以展开以填充我放置在其中的任何容器。如何实现相同的功能而不必先删除Height和Width值 建立我的控制权? (或者不使用父容器中的DockPanel。)
以下代码演示了该问题:
1 2 3 4 5 6 7 8 9
| <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的以下定义在设计时合理显示,但在运行时显示为固定大小:
1 2 3 4 5 6
| <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:
1 2 3 4 5
| <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> |
对于Blend,一个鲜为人知的技巧是将这些属性添加到用户控件或窗口中:
1 2 3 4
| 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的原因。 ;)
在Visual Studio中,将Width和Height属性添加到您的UserControl XAML中,但是在后面的代码中插入
1 2 3 4 5 6 7 8 9
| public UserControl1()
{
InitializeComponent();
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
this.Width = double.NaN; ;
this.Height = double.NaN; ;
}
} |
这将检查控件是否在设计模式下运行。如果不是(即运行时),它将把Width和Height设置为NaN(不是数字),这是您在XAML中删除Width和Height属性时设置的值。
因此,在设计时,您将具有预设的宽度和高度(包括是否将用户控件放在窗体中),并且在运行时,它将根据其父容器停靠。
希望有帮助。
这是Silverlight设计器中的设计时属性列表。对于WPF设计者来说,它们是相同的。
它列出了设计器中所有可用的d:值,例如d:DesignHeight,d:DesignWidth,d:IsDesignTimeCreatable,d:CreateList等。
我一直都这样做。只需在实例化控件的地方将width和height值设置为" auto",就会覆盖该UserControl的设计时值。
即:
另一种选择是将MinWidth和MinHeight的组合设置为允许设计时工作的大小,而Width和Height保持"自动"。显然,仅当您不需要UserControl的大小小于运行时的最小值时,这才有效。
我一直在寻找类似的解决方案,例如Blend中使用的解决方案,并且提到了我,我创建了具有两个附加属性Width和Height的简单行为类,这些属性仅在DesinTime中应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| 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中设置这些属性
1 2 3 4 5 6 7 8 9 10
| <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。这样,您将在设计器中看到它,并且在运行时它将按您希望的方式调整大小。
有人建议使用我从未见过的LicenseManager.UsageMode属性,但我使用了以下代码。
1 2 3 4 5
| if(!DesignerProperties.GetIsInDesignMode(this))
{
this.Width = double.NaN;
this.Height = double.NaN;
} |
埃斯卡,
我只想补充一点,在覆盖" On"方法时,通常应始终调用基类的方法。
1 2 3 4 5 6
| protected override void OnVisualParentChanged(DependencyObject oldParent)
{
base.OnVisualParentChanged(oldParent);
...
} |
顺便说一句,很好的解决方法,我现在也在自己使用。
感谢此解决方案的原始答复者!对于那些感兴趣的人,这里是VB:
1 2 3 4
| If LicenseManager.UsageMode <> LicenseUsageMode.Designtime Then
Me.Width = Double.NaN
Me.Height = Double.NaN
End If |
我做类似的事情,但是我的解决方案确保了,如果您在设计模式下将控件添加到容器中,它将看起来很合理。
1 2 3 4 5 6 7 8
| protected override void OnVisualParentChanged(DependencyObject oldParent)
{
if (this.Parent != null)
{
this.Width = double.NaN;
this.Height = double.NaN;
}
} |
你怎么看?