使用XAML +设计器编辑普通的旧CLR对象?

时间:2009-06-23 12:43:41

标签: wpf xaml poco

我想在XAML中编写POCO,并使用DataTemplate在运行时在GUI中显示该对象。到现在为止还挺好;我知道如何做到这一切。

因为我已经有了一个可以将我的POCO转换为WPF可视化树的DataTemplate,有没有办法让Visual Studio设计师一起玩,而让设计视图向我展示POCO + DataTemplate的当我编辑POCO的XAML时生成GUI?(显然设计师不知道如何编辑“设计视图”;我不希望工具箱或点击 - 和 - 拖动以在设计界面上工作。这很好 - 我只想在编辑时看到预览。)

如果你很好奇,那么有问题的POCO就是游戏的等级地图。 (此时,我不打算发布最终用户地图编辑器,所以我将在Visual Studio中自己进行所有编辑。)因此,XAML不是像Window和UserControl这样的WPF GUI对象,但它是仍然不是我想盲目地敲出一些XAML并希望最好的东西。我想看看我正在做什么(GUI地图),就像我正在做的那样。

如果我尝试创建一个根目录是我的地图对象的XAML文件,设计器会显示“故意留空 - 视觉设计器不支持文档根元素”。即使我在App.xaml的<Application.Resources>中定义了一个DataTemplate,它也会这样做。

但我知道设计师可以显示我的POCO,当它在WPF对象中时。实现我想要的一种可能方法是使用一个只包含ContentPresenter的ScratchUserControl,并在ContentPresenter的Content属性中写入我的POCO XAML,例如:

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

但是当我完成编辑时,我必须确保将内容复制回自己的文件中,这看起来很乏味且容易出错,而且我不喜欢单调乏味且容易出错。既然我可以以这种方式预览我的XAML,没有UserControl就没有办法做到这一点吗?

2 个答案:

答案 0 :(得分:2)

我现在正在这样做,实际上。创建ResourceDictionary并从其他XAML文件引用它。例如,制作一个包含普通旧对象的文件,即:

<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是x:Key,你在其XML文件中给出了POCO(在这种情况下,我给出了引用的POCO对象,ArrayList, “PreferenceList”键)

答案 1 :(得分:0)

我很确定你不会在这里得到你想要的东西。

WPF在设计窗口中不会以逻辑方式处理太多。这包括(在大多数情况下)您在XAML数据绑定中使用的DataTemplate和IValueConverter对象,因为这些对象通常与在运行时之前未实例化的(POCO)对象一起使用。

这可以解释为什么它在UserControl示例中起作用,因为您正在XAML中明确地创建Map POCO的实例。设计器窗口绝对不会尝试渲染任何基于绑定或模板的内容,这些绑定或模板引用Visual Studio无法在设计时实例化的对象。这基本上意味着如果您尝试在幕后的C#(或其他)代码中创建这些对象,则无法将对象显示在设计窗口中。您的后端代码无法由设计窗口运行,因为它必须由编译器构建并在任何执行之前运行。 (早期版本的Visual Studio使用极端的解决方法来尝试解决此问题,而Microsoft不再提供此支持。)像XAML这样的标记语言没有这个限制,因为它们不包含逻辑执行序列,因此设计窗口可以将它们呈现在屏幕仅使用已解析的XAML标记。

在坚果壳中,我认为XAML设计窗口并不打算以您尝试使用它的方式使用。

如果您真的希望能够在设计器中看到您的POCO,但您不想将其插入带有ContentPresenter的UserControl中 - 请尝试从适当的根元素派生您的POCO设计人员可以渲染,并添加一个Serialize方法来读取/写入文件。

如果这些解决方案不适合您,那么您可能不得不在设计窗口中处理Visual Studio而不是渲染Map对象。也许这会给你一些创造独立地图编辑器的动力,即使你没有把它发给最终用户。您可能希望花时间编写一个简单的编辑器,即使它仅供您使用。 Visual Studio不会替换您的自定义地图编辑器 - 至少,不会以任何对您有用的方式。