2

I want to write a POCO in XAML, and use a DataTemplate to display that object in the GUI at runtime. So far, so good; I know how to do all that.

Since I'll already have a DataTemplate that can transform my POCO into a WPF visual tree, is there any way to get the Visual Studio designer to play along, and have the Design View show me the POCO+DataTemplate's resulting GUI, as I edit the POCO's XAML? (Obviously the designer wouldn't know how to edit the "design view"; I wouldn't expect the Toolbox or click-and-drag to work on the design surface. That's fine -- I just want to see a preview as I edit.)

If you're curious, the POCOs in question would be level maps for a game. (At this point, I'm not planning to ship an end-user map editor, so I'll be doing all the editing myself in Visual Studio.) So the XAML isn't WPF GUI objects like Window and UserControl, but it's still not something where I would want to blindly bang out some XAML and hope for the best. I want to see what I'm doing (the GUI map) as I'm doing it.

If I try to make a XAML file whose root is my map object, the designer shows "Intentionally Left Blank - The document root element is not supported by the visual designer." It does this even if I've defined a DataTemplate in App.xaml's <Application.Resources>.

But I know the designer can show my POCO, when it's inside a WPF object. One possible way of accomplishing what I want would be to have a ScratchUserControl that just contains a ContentPresenter, and write my POCO XAML inside that ContentPresenter's Content property, e.g.:

<UserControl ...>
    <ContentPresenter>
        <ContentPresenter.Content>
            <Maps:Map .../>
        </ContentPresenter.Content>
    </ContentPresenter>
</UserControl>

But then I would have to be sure to copy the content back out into its own file when I was done editing, which seems tedious and error-prone, and I don't like tedious and error-prone. And since I can preview my XAML this way, isn't there some way to do it without the UserControl?

4

2 に答える 2

2

私は実際に今これをやっています。ResourceDictionary を作成し、他の XAML ファイルから参照します。たとえば、プレーンな古いオブジェクトを含む 1 つのファイルを作成します。つまり、次のようになります。

<Windows:ResourceDictionary>
  <Collections:ArrayList x:Key="PreferenceList">
    <NumericPreference id="server.port"
     helpText="The port on which the server should listen for incoming connections (default is 30588)"
     min="1"
     max="65535"
     step="1"
     displayName="Port"
     validationName="Port number" />
  </Collections:ArrayList>
</Windows:ResourceDictionary>

(NumericPreference は POCO に置き換えられます)、次のように参照します。

<UserControl>
  <UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Preferences.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </UserControl.Resources>
  <Grid>
    <!-- Your code here -->
  </Grid>
</UserControl>

...しかし、はい、デザイナーの結果を表示するには、「スクラッチ ユーザー コントロール」を接続する必要がありますが、コピーと貼り付けは必要ありません。ここで重要な部分は、ResourceDictionary Source="YourStaticResource.xaml" です。

マップをルート要素として持つことはできません (ルート要素は ResourceDictionary でなければなりません) が、ResourceDictionary の唯一の子要素として持つことはできます。

リソースを参照するには、もちろん {StaticResource XXX} または {DynamicResource XXX} を使用します。XXX は、XML ファイルで POCO に指定した x:Key です (この場合、参照される POCO オブジェクト、ArrayList、"PreferenceList " 鍵)

于 2009-08-11T03:37:07.593 に答える
0

ここであなたが望むものを手に入れることはできないと確信しています。

WPF は、デザイン ウィンドウのロジックをあまり処理しません。これには、XAML データ バインディングで使用する DataTemplate および IValueConverter オブジェクトが (ほとんどの場合) 含まれます。これらのオブジェクトは通常、実行時までインスタンス化されない (POCO) オブジェクトで動作するためです。

これは、XAML でマップ POCO のインスタンスを明確に作成しているため、UserControl の例で機能する理由を説明できます。デザイナー ウィンドウは、デザイン時に Visual Studio がインスタンス化できないオブジェクトを参照するバインディングまたはテンプレートに基づくものをレンダリングしようとしません。これは基本的に、バックグラウンドで C# (またはその他のコード) でオブジェクトを作成しようとしている場合、オブジェクトをデザイン ウィンドウに表示できないことを意味します。バックエンド コードは、コンパイラによってビルドされ、実行される前に実行される必要があるため、デザイン ウィンドウで実行することはできません。(Visual Studio の以前のバージョンでは、極端な回避策を使用してこれを解決しようとしましたが、Microsoft はこのサポートを提供しなくなりました。) XAML のようなマークアップ言語は、

一言で言えば、XAML デザイン ウィンドウは、あなたが使用しようとしている方法で使用されることを意図したものではないと思います。

デザイナーで POCO を表示できるようにしたいが、ContentPresenter を使用して UserControl に挿入する必要がない場合 --- デザイナーがレンダリングできる適切なルート要素から POCO を派生させてみてください。 、および Serialize メソッドを追加して、ファイルとの間で読み取り/書き込みを行います。

これらの解決策がうまくいかない場合は、Visual Studio がデザイン ウィンドウに Map オブジェクトをレンダリングしないように対処する必要があります。エンドユーザーに出荷しなくても、スタンドアロンのマップ エディターを作成する動機が得られるかもしれません。たとえそれがあなただけのものであっても、単純なエディタを書くために時間を費やしたいと思うかもしれません。Visual Studio は、カスタム マップ エディターに取って代わるものではありません。少なくとも、あなたにとって役立つ方法ではありません。

于 2009-06-30T00:31:10.290 に答える