【发布时间】:2013-10-14 11:28:32
【问题描述】:
场景: 创建一个 MarkupExtension 以将 Grid.Row=”0” 替换为 Grid.Row=”{namespace:ClassExtension GridRowName}”(列相同)
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 错误 被使用了
- 当 Valid ColumnName 用于 Row 声明时(以及 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 方法抛出的,但原因是 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 调用,它对 columndefinition 工作正常,但对 rowdefinition 失败......:
栏:
行:
此时,我不知道该怎么办了……
源代码(示例项目)位于:http://www.frederikprijck.net/stuff/MarkupExtension.rar
【问题讨论】:
-
只是一个建议。在您的帖子中使用实际代码(就像您对 xaml 所做的那样),而不是代码的屏幕截图。在 SO 中调整大小时,其中一些屏幕截图非常小。
-
我使用屏幕截图是因为我想指出所有问题:Xaml 下划线、c# 运行时值……我用代码替换了一些屏幕截图,因为您是对的。我想我开始使用屏幕截图并尽可能忘记使用文本。顺便说一句,我出于这些原因添加了源项目:-)
标签: c# wpf xaml design-time markup-extensions