web-dev-qa-db-ja.com

WPF UserControlデザインタイムサイズ

WPFでUserControlを作成するとき、Visual Studioデザイナーで変更を表示できるように、任意のHeightおよびWidth値を指定すると便利です。ただし、コントロールを実行するときは、HeightとWidthを未定義にして、コントロールが配置されているコンテナに合わせて拡張されるようにします。コントロールを構築しますか? (または、親コンテナで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>
51

Visual Studioで、UserControl XAMLにWidth属性とHeight属性を追加しますが、コードビハインドにこれを挿入します

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

これにより、コントロールがデザインモードで実行されているかどうかが確認されます。そうでない場合(つまり、ランタイム)、XAMLでWidthおよびHeight属性を削除した場合に設定した値であるNaN(非数値)にWidthおよびHeightを設定します。

そのため、設計時にはプリセットの幅と高さ(フォームにユーザーコントロールを配置する場合を含む)があり、実行時には親コンテナーに応じてドッキングされます。

お役に立てば幸いです。

38
Alex Duggleby

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 Designerではありません。

Visual Studio Designerに関しては、あなたのテクニックがすべて機能します。 Visual Studio Designerを使用しないのはこのためです。 ;)

79
Brian Leahy

Silverlightデザイナのデザイン時属性 のリストを次に示します。 WPFデザイナーにとっても同じです。

d:d:DesignHeightd:DesignWidthd:IsDesignTimeCreatableなど、Designerで使用可能なすべてのd:CreateList値がリストされます。

8
CLaRGe

私はいつもこれをしています。コントロールをインスタンス化する場所で幅と高さの値を「自動」に設定するだけで、そのユーザーコントロールのデザイン時の値が上書きされます。

すなわち:<loc:UserControl1 Width="auto" Height="auto" />

もう1つのオプションは、MinWidthとMinHeightの組み合わせを、設計時の作業が可能なサイズに設定する一方で、WidthとHeightを「自動」のままにすることです。明らかに、これは、実行時の最小値よりも小さいサイズにUserControlを必要としない場合にのみ機能します。

6
AndyL

Blendで使用されるものと同様のソリューションを探していましたが、あなたの言及で、DesiTimeにのみ適用される2つの添付プロパティ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(DesignerPropertie s.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、 DependencyPropertyChangedEven tArgs 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> 
2
Ondrej

コントロールでMinWidthとMinHeightを使用します。そうすれば、デザイナーでそれを見ることができ、実行時にそれはあなたが望むようにサイズを調整します。

1
Roger Dufresne

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

    ...
}

ところで、素晴らしい回避策は、私も今自分で使っています。

0
jpierson

私はそれを同様に行いますが、私のソリューションは、デザインモードでコンテナにコントロールを追加すると、合理的に表示されることを保証します。

protected override void OnVisualParentChanged(DependencyObject oldParent)
{
    if (this.Parent != null)
    {
       this.Width = double.NaN;
       this.Height = double.NaN;
    }
}

どう思いますか?

0
esskar

このソリューションの元の回答者に感謝します!興味のある人のために、ここではVBにあります:

If LicenseManager.UsageMode <> LicenseUsageMode.Designtime Then
    Me.Width = Double.NaN
    Me.Height = Double.NaN
End If
0
Paul