문제

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에서는 UserControl XAML에 Width 및 Height 특성을 추가하지만 코드 숨김에는 다음을 삽입합니다.

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

이는 컨트롤이 디자인 모드에서 실행되고 있는지 확인합니다.그렇지 않은 경우(예:런타임) Width 및 Height는 XAML에서 Width 및 Height 특성을 제거한 경우 설정한 값인 NaN(숫자 아님)으로 설정됩니다.

따라서 디자인 타임에는 미리 설정된 너비와 높이(사용자 컨트롤을 양식에 넣는 경우 포함)를 갖게 되며 런타임에는 상위 컨테이너에 따라 도킹됩니다.

도움이 되길 바랍니다.

다른 팁

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 Designer의 디자인 타임 특성.WPF 디자이너도 마찬가지입니다.

그것은 모든 것을 나열합니다 d: 다음과 같이 디자이너에서 사용할 수 있는 값 d:DesignHeight, d:DesignWidth, d:IsDesignTimeCreatable, d:CreateList 그리고 다른 몇몇.

나는 항상 이것을 한다.컨트롤을 인스턴스화할 때 너비와 높이 값을 "자동"으로 설정하면 해당 UserControl의 디자인 타임 값이 재정의됩니다.

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

또 다른 옵션은 MinWidth와 MinHeight의 조합을 디자인 타임 작업을 허용하는 크기로 설정하고 Width와 Height는 "자동"으로 유지하는 것입니다.분명히 이것은 런타임에 최소값보다 작은 크기로 UserControl이 필요하지 않은 경우에만 작동합니다.

나는 Blend에서 사용되는 것과 유사한 솔루션을 찾고 있었고 귀하의 언급에 따라 DesinTime에만 적용되는 Width 및 Height 두 속성이 연결된 간단한 동작 클래스를 만들었습니다.

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);

    ...
}

그건 그렇고, 훌륭한 해결 방법은 지금도 나 자신도 사용하고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top