Подтвердить что ты не робот

Размер времени разработки пользовательского интерфейса 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>
4b9b3361

Ответ 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);

    ...
}

Великий обходной путь, кстати, я тоже сам использую его.