5

XAML デザイン データ ファイルで同じオブジェクトを 2 回 (またはそれ以上) 参照するにはどうすればよいですか? を使用しようとしまし{x:Reference}たが、これは機能しないようです。

次に例を示します。

サンプルのデータ グリッドの 2 列目のセルにあるコンボ ボックスには、「データ型」のリストが表示されます。利用可能なデータ型のリストはTypes、メイン ウィンドウのビュー モデル (= データ コンテキスト) のプロパティから取得されます。グリッド内のアイテムのリストはItems、ビュー モデルのプロパティから取得されます。各項目にはNameType列があり、Type はデータ型オブジェクトを参照します。

サンプル グリッドは次のようになります。

スクリーンショット

Visual Studio デザイナーで同じグリッド コンテンツを表示する必要がある XAML デザイン データを次に示します (実際には表示されません)。

<?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:ReferenceXAML 2009 の機能です。

x:ReferenceMSDN ドキュメントに従ってコンパイルされた XAML マークアップでは使用できません。

XAML ページ (.xaml) を作成し、Internet Explorer 経由でロードする場合など、ルーズ XAML 用に設計されています。

DesignData を使用すると、DesignData ファイルに記述されている形状と内容を持つ新しいクラスが Designer によって効果的に作成およびコンパイルされます。

Visual Studio/Blend Designers ではサポートされていません。

ここに反論があります。

Adam Nathan の WPF 4 unleashed book からの説明は次のとおりです。「x:Reference マークアップ拡張機能は、この記事の執筆時点でルース XAML からのみ使用できる XAML2009 機能と誤って関連付けられることがよくあります。x:Reference は新しい機能ですが、 WPF 4 では、プロジェクトがバージョン 4 以降の .NET Framework をターゲットにしている限り、XAML2006 から問題なく使用できます.1 つの問題は、Visual Studio 2010 の XAML デザイナーが x:Reference を適切に処理しないことです.そのため、次の設計時エラーが発生しますが、無視しても問題ありません: サービス プロバイダーに INameResolver サービスがありません"

回避策の解決策 ...

于 2012-09-07T11:27:18.490 に答える