【问题标题】:Using XAML + designer to edit Plain Old CLR Objects?使用 XAML + 设计器编辑普通旧 CLR 对象?
【发布时间】:2009-06-23 12:43:41
【问题描述】:

我想在 XAML 中编写 POCO,并使用 DataTemplate 在运行时在 GUI 中显示该对象。到目前为止,一切都很好;我知道该怎么做。

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

如果您好奇,所讨论的 POCO 将是游戏的关卡地图。 (此时,我不打算发布最终用户地图编辑器,所以我将在 Visual Studio 中自己完成所有编辑。)所以 XAML 不是像 Window 和 UserControl 这样的 WPF GUI 对象,但它是仍然不是我想盲目地敲出一些 XAML 并希望最好的东西。我想看看我在做什么(GUI 地图)。

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

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

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

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

【问题讨论】:

    标签: wpf xaml poco


    【解决方案1】:

    实际上,我现在正在这样做。创建一个 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 是您在其 XML 文件中为 POCO 提供的 x:Key(在这种情况下,我提供了引用的 POCO 对象 ArrayList, “PreferenceList”键)

    【讨论】:

    • 我希望在编辑 POCO 时能够看到设计器,但这需要我在 ResourceDictionary.xaml 和 ScratchControl.xaml 之间来回使用 Ctrl+Tab。但这可能是 VS 能做的最好的。
    • 您可以在 VS 中打开两个窗口/选项卡/可停靠的任何东西——一个用设计器打开,一个用 ResourceDictionary xaml 打开。你所需要的只是一个大得吓人的显示器。打开设计器和选项卡中的xaml,然后右键单击其中一个选项卡,然后选择“新建水平选项卡组”或“新建垂直选项卡组”。
    【解决方案2】:

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

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

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

    简而言之,我不认为 XAML 设计窗口曾经打算以您尝试使用它的方式使用。

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

    如果这些解决方案不适合您,那么您可能不得不处理 Visual Studio 未在设计窗口中呈现您的 Map 对象的问题。也许这最终会给您一些创建独立地图编辑器的动力,即使您没有将其发送给最终用户。您可能想花时间编写一个简单的编辑器,即使它仅供您使用。 Visual Studio 不会取代您的自定义地图编辑器 - 至少不会以任何对您有用的方式。

    【讨论】:

    • 我不是在谈论用 C# 创建地图。我在谈论将它作为 XAML 根元素,在这种情况下,我在 XAML 中创建它,就像在 UserControl 示例中一样清楚。没有理由 VS 无法 使用 App.xaml DataTemplates 呈现它。它似乎只是明确禁用了该场景,我希望有人知道解决它的方法。
    • 点了。我个人不希望设计窗口在任何类型的 DataTemplate 下呈现任何内容,尽管我承认我对它们的了解不够,无法确定没有任何解决办法。我希望我能给你更可靠的建议,但恐怕我只有这些了。很遗憾没有更多人回答 XAML 问题...
    猜你喜欢
    • 2010-10-18
    • 1970-01-01
    • 2011-01-16
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    相关资源
    最近更新 更多