这是一个设计时问题。代码编译并运行后,将传入正确的值。
1 - 使用作为ConverterParameter通过x:Name引用数据网格(根据MSDN信息,这是正确的)。 2 - 不能使用与ElementName的绑定,因为ConverterParameter不是依赖项属性。我想我可以创建一个依赖属性,它似乎没有必要,因为在某个时间点,x:引用已经解决..只是在设计时没有解决。
所以我有以下代码。这是一个模板,允许对过滤的列标题进行着色,因此它们在视觉上对用户来说是显而易见的:
<Converters:BGConverter x:Key="BackgroundConverter"/>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Black" BorderThickness="1" Width="150">
<StackPanel x:Name="testtest" Orientation="Horizontal"
Background="{Binding Converter={StaticResource BackgroundConverter}, ConverterParameter={x:Reference TestListView}}">
<Label Width="90" Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridColumnHeader}},Path=Column.Header}"
Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button Content="Ok" Padding="12,0,12,0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="20,0,0,0"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
问题在于“ConverterParameter =”{x:Reference TestListView}“部分。标记不编译,”GUI“仅显示”抛出了异常。 XamlObjectWriterException:未解析的引用'TestListView'。
同样,如果我单步执行代码并实际运行程序,则每个标头实际上都会正确传入转换器,并确定标题列颜色并正确显示。
Datagrid(引用的对象)声明如下(部分,不需要borderthickness或headersvisibility等等):
<DataGrid x:Name="TestListView" />
有没有办法修复设计器,以便它可以确定并找到x:Name?我读过2009年的文章说x:参考是新的,实际上并不是Xaml的一部分,但那是2009年,差不多是2015年。在6年内,这应该已被容纳或删除。
有关如何让编译器识别x:Name而不发疯并将其声明为静态或创建依赖属性的任何建议?由于它只是标记,我可以按原样使用它,它只会让我的强迫症疯狂。
答案 0 :(得分:3)
x:Reference
,它仍然基于Xaml2006规范。由于它是作为标记扩展而不是语言增强实现的,它在某些情况下仍会在运行时工作(尽管不是全部),但是设计者不支持它,并且没有办法使它在某种程度上不能扩展设计师自己。
您可以使用相同的服务实现与x:Reference
执行相同任务的自定义标记扩展,但在缺少所需服务的情况下(例如,在设计器中运行时),它会无声地失败:
[ContentProperty("Name")]
public class NameReferenceExtension : MarkupExtension
{
[ConstructorArgument("name")]
public string Name { get; set; }
public NameReferenceExtension() {}
public NameReferenceExtension(string name)
{
this.Name = name;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
throw new ArgumentNullException("serviceProvider");
var xamlNameResolver = serviceProvider.GetService(typeof(IXamlNameResolver))
as IXamlNameResolver;
if (xamlNameResolver == null)
return null; // fail silently
if (string.IsNullOrEmpty(this.Name))
throw new InvalidOperationException(
"Name is required when using NameReference.");
var resolved = xamlNameResolver.Resolve(this.Name);
if (resolved == null)
resolved = xamlNameResolver.GetFixupToken(new[] { this.Name }, true);
return resolved;
}
}