5

如何在 XAML 设计数据文件中引用同一对象两次(或更频繁)?我尝试使用{x:Reference},但这似乎不起作用。

这是一个例子:

样本数据网格第二列单元格中的组合框显示“数据类型”列表。可用数据类型的列表来自Types主窗口视图模型的属性(= 数据上下文)。网格中的项目列表来自Items视图模型的属性。每个项目都有一个Name和一个Type列,其中 Type 引用一个数据类型对象。

示例网格如下所示:

截屏

这是 XAML 设计数据,它应该在 Visual Studio 设计器中显示相同的网格内容(但它没有):

<?xml version="1.0" encoding="utf-8" ?>
<local:MainWindowViewModel
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:DataGridSample"
    >
    <local:MainWindowViewModel.Types>
        <local:DataType Name="String" x:Name="String"/>
        <local:DataType Name="Integer" x:Name="Integer"/>
    </local:MainWindowViewModel.Types>
    <local:MainWindowViewModel.Items>
        <local:Item Name="Lorem" Type="{x:Reference String}"/>
        <local:Item Name="Ipsum" Type="{x:Reference Integer}"/>
    </local:MainWindowViewModel.Items>
</local:MainWindowViewModel>

上面,我{x:Reference String}用来获取对由<local:DataType Name="String" x:Name="String"/>.

在 Visual Studio 设计器中,列表为空,并显示错误消息“在标记中找到错误:... DesignData.xaml”。在设计数据 XAML 文件的编辑器中,我收到错误消息“服务提供者缺少 INameResolver 服务”。

我可以在设计数据文件中使用任何替代方法{x:Reference}来引用对象吗?

为了完整起见,这里是我的示例的其余文件:

MainWindow.xaml:

<Window x:Class="DataGridSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        mc:Ignorable="d"
        Title="Sample" Height="300" Width="400"
        d:DataContext="{d:DesignData Source=DesignData.xaml}">
    <Window.Resources>
        <CollectionViewSource x:Key="types" Source="{Binding Types}"/>
    </Window.Resources>

    <Grid>
        <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="*"/>
                <DataGridComboBoxColumn SelectedItemBinding="{Binding Type}"
                                        ItemsSource="{Binding Source={StaticResource types}}" 
                                        DisplayMemberPath="Name"
                                        Header="Type" Width="*"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DataGridSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        readonly MainWindowViewModel _viewModel = new MainWindowViewModel();

        public MainWindow()
        {
            InitializeComponent();

            DataContext = _viewModel;
        }
    }
}

MainWindowViewModel.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace DataGridSample
{
    public class MainWindowViewModel
    {
        private readonly ObservableCollection<DataType> _dataTypes;
        private readonly ObservableCollection<Item> _items;

        public MainWindowViewModel()
        {
            DataType typeString = new DataType {Name = "String"};
            DataType typeInteger = new DataType {Name = "Integer"};

            _dataTypes = new ObservableCollection<DataType> {typeString, typeInteger};
            _items = new ObservableCollection<Item>
                {
                    new Item {Name = "Lorem", Type = typeString},
                    new Item {Name = "Ipsum", Type = typeInteger}
                };
        }

        public ObservableCollection<DataType> Types
        {
            get
            {
                return _dataTypes;
            }
        }

        public ObservableCollection<Item> Items
        {
            get
            {
                return _items;
            }
        }
    }

    public class DataType
    {
        public string Name { get; set; }
    }

    public class Item
    {
        public string Name { get; set; }

        public DataType Type { get; set; }
    }
}
4

1 回答 1

1

关于为什么x:Reference不起作用的背景......

x:Reference是 XAML 2009 的一项功能。

您不能x:Reference在根据 MSDN 文档编译的 XAML 标记中使用。

它是为松散的 XAML 设计的……例如,如果您创建一个 XAML 页面 (.xaml) 并通过 Internet Explorer 加载它。

当您使用 DesignData 时,Designer 有效地创建并编译了一个新类,其形状和内容与您的 DesignData 文件中描述的一样。

Visual Studio/Blend Designers 不支持它。

这是一个反驳的论点。

以下是 Adam Nathan 的 WPF 4 unleashed book 的解释:“x:Reference 标记扩展经常被错误地与 XAML2009 功能相关联,这些功能在撰写本文时只能从松散的 XAML 中使用。虽然 x:Reference 是一个新功能在 WPF 4 中,只要您的项目针对 .NET Framework 4 或更高版本,它就可以从 XAML2006 中使用。一个小故障是 Visual Studio 2010 中的 XAML 设计器没有正确处理 x:Reference,因此它给出了以下设计时错误,您可以放心地忽略:服务提供者缺少 INameResolver 服务”

解决方法...

于 2012-09-07T11:27:18.490 回答