Размер времени разработки пользовательского интерфейса WPF
При создании UserControl в WPF мне удобнее давать некоторые произвольные значения Height и Width, чтобы я мог просматривать мои изменения в дизайнере Visual Studio. Однако, когда я запускаю элемент управления, я хочу, чтобы высота и ширина были undefined, поэтому элемент управления будет расширяться, чтобы заполнить любой контейнер, в который я его помещаю. Как я могу получить эту же функциональность, не удаляя высоту и ширину ценностей, прежде чем строить свой контроль? (Или без использования 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>
Ответы
Ответ 1
В Visual Studio добавьте атрибут "Ширина и высота" в ваш UserControl XAML, но вставьте его в код
public UserControl1()
{
InitializeComponent();
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
this.Width = double.NaN; ;
this.Height = double.NaN; ;
}
}
Это проверяет, работает ли элемент управления в режиме разработки. Если нет (то есть время выполнения), он установит ширину и высоту в NaN (не число), которое является значением, которое вы установили для этого, если вы удаляете атрибуты Width и Height в XAML.
Таким образом, во время разработки вы будете иметь заданную ширину и высоту (в том числе, если вы поместите элемент управления пользователя в форму), и во время выполнения он будет состыкован в зависимости от своего родительского контейнера.
Надеюсь, что это поможет.
Ответ 2
Для 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. Однако это будет работать только для дизайнера blend. Не Visual Studio Designer.
Что касается Visual Studio Designer, то ваша техника работает. Вот почему я не использую Visual Studio Designer.;)
Ответ 3
Вот список Атрибуты времени разработки в Silverlight Designer. Они одинаковы для дизайнера WPF.
В нем перечислены все значения d:
, доступные в конструкторе, такие как d:DesignHeight
, d:DesignWidth
, d:IsDesignTimeCreatable
, d:CreateList
и несколько других.
Ответ 4
Я делаю это все время. Просто установите значения ширины и высоты в "авто", где вы создаете экземпляр своего элемента управления, и это переопределит значения времени разработки для этого UserControl.
т.е.: <loc:UserControl1 Width="auto" Height="auto" />
Другой вариант - установить комбинацию MinWidth и MinHeight в размер, который позволяет работать с временем разработки, а ширина и высота остаются "авто". Очевидно, что это работает, только если вам не нужен размер UserControl, размер которого меньше минимальных значений во время выполнения.
Ответ 5
Я искал аналогичное решение, подобное тому, которое использовалось в Blend, и с вашими упоминаниями я создал простой класс поведения с двумя прикрепленными свойствами Width и Height, которые применяются только в 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>
Ответ 6
Используйте MinWidth и MinHeight для элемента управления. Таким образом, вы увидите его в дизайнере, и во время выполнения он будет таким же, как вы хотите.
Ответ 7
Я делаю это похоже, но мое решение гарантирует, что если вы добавите свой контроль в контейнер в режиме разработки, он будет выглядеть разумно.
protected override void OnVisualParentChanged(DependencyObject oldParent)
{
if (this.Parent != null)
{
this.Width = double.NaN;
this.Height = double.NaN;
}
}
как вы думаете?
Ответ 8
Благодаря оригинальному ответчику для этого решения! Для тех, кого это интересует, здесь он находится в VB:
If LicenseManager.UsageMode <> LicenseUsageMode.Designtime Then
Me.Width = Double.NaN
Me.Height = Double.NaN
End If
Ответ 9
Некоторые предложили использовать свойство 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);
...
}
Великий обходной путь, кстати, я тоже сам использую его.