【问题标题】:x:Reference cannot find x:Name in design mode - compiles and runs finex:Reference 在设计模式下找不到 x:Name - 编译并运行良好
【发布时间】:2014-10-20 15:03:56
【问题描述】:

这是一个设计时问题。代码编译运行后,传入正确的值。

1 - 用作通过 x:Name 引用数据网格的 ConverterParameter(根据 MSDN 信息,这是正确的)。 2 - 不能使用与 ElementName 的绑定,因为 ConverterParameter 不是依赖属性。我想我可以创建一个依赖属性,它似乎没有必要,因为在某个时间点,x:Reference 已解决。只是在设计时没有解决。

所以我有以下代码。这是一个允许对过滤后的列标题进行着色的模板,因此用户可以直观地注意到它们:

<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(被引用的对象)声明如下(部分,不需要borderthicknesses或headersvisibility等...):

<DataGrid x:Name="TestListView" />

有没有办法修复设计器,以便它可以确定并找到 x:Name?我读过 2009 年的文章说 x:Reference 是新的,实际上并不是 Xaml 的一部分,但那是 2009 年,快到 2015 年了。在 6 年内,这应该被容纳或删除。

关于如何让编译器识别 x:Name 而不会发疯并将其声明为静态或创建依赖属性的任何建议?由于它只是标记,我可以按原样接受它,它只会让我的强迫症发疯。

【问题讨论】:

    标签: c# wpf xaml datagrid markup


    【解决方案1】:

    x:Reference 在编译的 Xaml 中不受官方支持,它仍然基于 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;
        }
    }
    

    【讨论】:

    • 谢谢迈克,我想可能是这样的。似乎需要很长时间才能不更新规格,但是唉,我们能做些什么呢?哈哈。谢谢。我会将它打开一段时间,以防有人有解决方法,但如果没有发布解决方法,我会在 COB 之前将其标记为已回答。
    • 使用x:Reference 的自定义替代方案更新了答案,但由于它使用相同的底层服务,因此在设计器中运行时不会产生值(尽管它不会产生异常,要么)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    相关资源
    最近更新 更多