2

以下に実装されているように、単一の依存関係プロパティを持つ基本的な WinRT XAML UserControl があります。ユーザー コントロールは、別の Page または UserControl で使用される場合にのみ、デザイン時にのみ構築されるようです。ユーザーコントロール自体を使用してデザイナーで作業すると、テキスト「Hello world」がレンダリングされません。この場合も、デザイナにユーザー コントロールをデータで初期化させるにはどうすればよいですか?

XAML:

<UserControl
    x:Class="GTWin8.Ui.SimpleBinding"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:GTWin8.Ui"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400"
    x:Name="ThisControl">

    <Grid Background="Black">
        <TextBlock Text="{Binding Path=Message, ElementName=ThisControl}" 
                   HorizontalAlignment="Left" Margin="10,10,0,0" 
                   TextWrapping="Wrap" VerticalAlignment="Top" Height="280" Width="380"/>
    </Grid>
</UserControl>

分離コード:

public sealed partial class SimpleBinding : UserControl
{
    public static DependencyProperty MessageProperty = DependencyProperty.Register(
           "Message", typeof(String), typeof(SimpleBinding), new PropertyMetadata(null));

    public String Message
    {
        get { return (String)GetValue(MessageProperty); }
        set { SetValue(MessageProperty, value); }
    }

    public SimpleBinding()
    {
        this.InitializeComponent();
        Message = "Hello world";
    }
}
4

2 に答える 2

5

もっと簡単な方法は、宣言型呼び出しです。

<UserControl>

    <d:Page.DataContext>
        <sample:FakeViewModel />
    </d:Page.DataContext>

    <Grid>
        <!-- your bind/content -->
    </Grid>

</UserControl>

ランタイム エクスペリエンスを妨げることなく設計時のデータを提供するため、すべてのプロジェクトでこれを使用しています。詳細: http://blog.jerrynixon.com/2012/06/windows-8-15-more-reasons-why-i-choose.html

于 2012-08-09T17:40:13.400 に答える
3

IIRC、あなたが書いた直接の形式では、これを達成することは不可能です。これは、設計時にコントロールのインスタンスを操作しないためです。XAML の最初の行に注意してください。ルート要素は、基本クラスである UserControl を指定しています。これはあなたが扱うインスタンスです!これが、抽象基底クラスを持つコンポーネントの設計に常に問題があった理由です。デザイナーで操作するものはすべて、XAML によって指定されたコンテンツで満たされた UserControl インスタンスです。

XAML パーサーは、タグ名で記述されたすべてのオブジェクトをインスタンス化します。コントロールを設計しているとき、コントロールは実際にはまだ存在しないため、パーサーはそれをインスタンス化できません。これがまさに、XAML の最初の単語が UserControl であり、クラス名が x:Class 属性として与えられる理由です。XAML を保存すると、部分クラスを指定した MyControl.g.cs ファイルに前処理され、独自の MyControl.cs とペアになってコンパイルされ、その後で初めて Visual Studio (またはアプリ) が実行されます。含まれているコードを呼び出すことができます。

一生懸命やると、XAML パーサーに強制的にコントロールを読み込ませることができますが、それは何のためでしょうか? 現在編集されているものではなく、前のビルドのスナップショットがあります。XAML テンプレートのみが動的にドロップおよびロードされるため、最新の状態に保たれます。

それは、「コンストラクターが実行されなかった理由」の部分です。

Message を ctor に設定する必要がある場合は、デフォルトのプロパティ値として設定しないでください。

public sealed partial class SimpleBinding : UserControl
{
    public static DependencyProperty MessageProperty = DependencyProperty.Register(
           "Message", typeof(String), typeof(SimpleBinding), new PropertyMetadata("Hello world"));
...
    public SimpleBinding()
    {
        this.InitializeComponent();
    }
}

もちろん、コンストラクターで分岐/計算/などできるものとは対照的に、非常に制限され、ハードコーディングされています。もっと自由が必要な場合は、Design Time Data を試してみてください。少しは役立つかもしれません。

個別の設計時にコンポーネント内でカスタム コードを実行する必要がある場合は、コードをダミーの基本クラスに移動し、XAML のルートに <UserControl> ではなく < MyBaseClass > を配置することを検討してください。XAML パーサーは強制的にインスタンス化してから、xaml の内容でスキンを適用します。その基本クラスの以前の成功したビルドを呼び出すことに注意してください。また、動作をフィルタリングするために IsInDesignMode または同様のものを使用することを忘れないでください (例: https://stackoverflow.com/a/426072/717732を参照)。

于 2012-08-08T15:09:09.390 に答える