7

シナリオ: Grid.Row=”0” を Grid.Row=”{namespace:ClassExtension GridRowName}” に置き換える MarkupExtension を作成します (列も同じ)

Xaml コード:

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" x:Name="TitleRow" />
    <RowDefinition Height="Auto" x:Name="LastNameRow" />
    <RowDefinition Height="Auto" x:Name="FirstNameRow" />
    <RowDefinition Height="Auto" x:Name="EmailRow" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition x:Name="LabelColumn" />
    <ColumnDefinition x:Name="ValueColumn" />
  </Grid.ColumnDefinitions>

    <Label Grid.Row="{me:GridDefinition Name=TitleRow}" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" />
    <Label Grid.Row="{me:GridDefinition Name=LastNameRow}" Grid.Column="{me:GridDefinition Name=LabelColumn}" FontWeight="Bold" FontSize="14" />
</Grid>

要件:

  • 正しくない GridRowName (または columnName) が使用されている場合に XAML エラーを表示する
  • 正しい GridRowName (または columnName) が使用されている場合に XAML エラーを表示しない
  • Row 宣言に有効な ColumnName が使用されている場合 (および vica verca)、XAML エラーが表示されます。

問題: Grid.Column ではすべて正常に動作しますが、Grid.Row は設計時に常に「実装されていない例外」をスローします (grid.row には下線が引かれ、grid.column には下線が引かれません)。 ここに画像の説明を入力

行と列の名前はどちらも正しいですが、行には常にエラーが表示されます。無効な列名を指定すると、列にエラーが表示されます (これは予想されることなので、Grid.Column は正常に動作します!) ここに画像の説明を入力

ご覧のとおり、列は正常に機能しますが、行は機能しません。問題は、GridDefinitionExtension と呼ばれる MarkupExtension 内にあります。

[MarkupExtensionReturnType(typeof(int))]
public class GridDefinitionExtension : MarkupExtension
{
    public string Name { private get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var referenceExt = new Reference(Name);
        var definition = referenceExt.ProvideValue(serviceProvider);

        if (definition is DefinitionBase)
        {
            var grid = (definition as FrameworkContentElement).Parent as Grid;

            if (grid != null && definition is RowDefinition)
                return grid.RowDefinitions.IndexOf(definition as RowDefinition);

            if (grid != null && definition is ColumnDefinition)
                return grid.ColumnDefinitions.IndexOf(definition as ColumnDefinition);
        }

        // This Extension only works for DefinitionBase Elements.
        throw new NotSupportedException();
    }
}

例外は次の行にあります。

var definition = referenceExt.ProvideValue(serviceProvider);

このメソッドが呼び出された DLL を調べたところ、この ProvideValue メソッドの本体は次のようになっていることがわかりました。

public override object ProvideValue(IServiceProvider serviceProvider)
{
  if (serviceProvider == null)
    throw new ArgumentNullException("serviceProvider");
  IXamlNameResolver xamlNameResolver = serviceProvider.GetService(typeof (IXamlNameResolver)) as IXamlNameResolver;
  if (xamlNameResolver == null)
    throw new InvalidOperationException(System.Xaml.SR.Get("MissingNameResolver"));
  if (string.IsNullOrEmpty(this.Name))
    throw new InvalidOperationException(System.Xaml.SR.Get("MustHaveName"));
  object obj = xamlNameResolver.Resolve(this.Name);
  if (obj == null)
  {
    string[] strArray = new string[1]
    {
      this.Name
    };
    obj = xamlNameResolver.GetFixupToken((IEnumerable<string>) strArray, true);
  }
  return obj;
}

この ProvideValue メソッドを簡略化して、シナリオで実際に使用しているコードのみを表示しました。

if (serviceProvider == null)
    throw new ArgumentNullException("serviceProvider");

IXamlNameResolver xamlNameResolver = serviceProvider.GetService(typeof(IXamlNameResolver)) as IXamlNameResolver;

object obj = xamlNameResolver.Resolve(this.Name);
if (obj == null)
{
    var strArray = new string[1]{ this.Name };
    obj = xamlNameResolver.GetFixupToken((IEnumerable<string>)strArray, true);
}
return obj;

どうやら GetFixUpToken メソッドによって Exception がスローされているようですが、原因は Resolve メソッドにあります。この Resolve メソッドは、ColumnDefinition をその名前でルックアップすると有効なオブジェクトを返しますが、RowDefinition に対してまったく同じことを行うと NULL を返します。

GetFixUpToken によってスローされるエラーは、「NotImplementedException」です。これは、IXamlNameResolver のソースコード (この場合はタイプ: XamlNameResolverImpl) を見ると予想されるものです。

ここに画像の説明を入力

この XamlNameResolverImpl のソース コードを見ると、メソッド「GetFixUpToken」が空であり、NotImplemented 例外をスローしていることがわかります ( http://dotnetinside.com/en/framework/Microsoft+Expression/Microsoft.Expression.WpfPlatformを参照)。 /WpfMarkupExtensionValueSetter )

public object GetFixupToken(IEnumerable<string> names, bool canAssignDirectly)
{
      throw new NotImplementedException();
}
public object GetFixupToken(IEnumerable<string> names)
{
      throw new NotImplementedException();
}

しかし、問題は、既に述べたように、Resolve 呼び出しです。これは、列定義では問題なく機能しますが、行定義では失敗します…

桁: ここに画像の説明を入力

行: ここに画像の説明を入力

この時点で、私はもう何をすべきかわかりません...

ソース コード (サンプル プロジェクト) は、http: //www.frederikprijck.net/stuff/MarkupExtension.rarで入手できます。

4

1 に答える 1