【问题标题】:WinRT information: Cannot find a resource with the given key. Issues with converter referenceWinRT 信息:找不到具有给定密钥的资源。转换器参考问题
【发布时间】:2017-02-05 16:26:04
【问题描述】:

我在启动 UWP 应用时收到此错误。它未能找到 FirstNameToVisibilityConverter 资源。如果有人能找出我收到此错误的原因,或者使用转换器发布一个 UWP 应用程序的小型工作示例,我将不胜感激。谢谢!

XAML:

<UserControl
    x:Class="MyHelloWorld.HelloWorld"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MyHelloWorld"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

<Grid>
    <Grid.Resources>
        <local:FirstNameToVisibilityConverter x:Key="FirstNameToVisibilityConverter"/>
        <p:Style TargetType="TextBox">
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
        </p:Style>
    </Grid.Resources>
    <StackPanel>
        <TextBlock Foreground="Red">HI</TextBlock>
        <TextBlock Foreground="Red">THERE</TextBlock>
        <TextBox Foreground="Red" Text="{x:Bind FirstWord}"/>
        <TextBlock Foreground="Red" Text="{x:Bind SecondWord}" Visibility="{x:Bind FirstWord, Converter={StaticResource FirstNameToVisibilityConverter}}"/>
        <CheckBox Foreground="Red" Content="Click me to hide the first word" IsChecked="{x:Bind FirstWordChecked}"/>
    </StackPanel>
</Grid>

代码背后:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace MyHelloWorld
{
    public sealed partial class HelloWorld : UserControl
    {
        public string FirstWord { get; set; }
        public string SecondWord { get; set; }
        public bool? FirstWordChecked { get; set; }

        public HelloWorld()
        {
            this.InitializeComponent();
        }
    }

    public class FirstNameToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if ((string)value == "Today") return Visibility.Collapsed;
            return Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }  
}

【问题讨论】:

  • 我没有看到代码有任何问题。您是否在转换器中尝试了 BreakPoint 并查看它是否命中?
  • NVM。但是您是否尝试将您的{x:Bind} 更改为{Binding} 以查看它是否有效? {x:Bind} 是编译时间,{Binding} 是运行时间。

标签: c# wpf uwp


【解决方案1】:

这是因为您使用的是编译时绑定扩展 {x:Bind} 而不是运行时绑定扩展 {Binding},再加上 XAML 编译器将 Converter 属性作为特殊情况处理这一事实,生成一个显式的LookupConverter() 方法来查找转换器:

public global::Windows.UI.Xaml.Data.IValueConverter LookupConverter(string key)
{
    if (this.localResources == null)
    {
        global::Windows.UI.Xaml.FrameworkElement rootElement;
        this.converterLookupRoot.TryGetTarget(out rootElement);
        this.localResources = rootElement.Resources;
        this.converterLookupRoot = null;
    }
    return (global::Windows.UI.Xaml.Data.IValueConverter) (this.localResources.ContainsKey(key) ? this.localResources[key] : global::Windows.UI.Xaml.Application.Current.Resources[key]);
}

虽然正常的资源查找规则会遍历对象树,递归地检查每个父对象,直到找到给定名称的资源,正如您在上面看到的,显式生成的方法绕过了ResourceDictionary 行为,并且只查找根级Resources(即UserControl对象的Resources),或应用程序Resources

因此,您需要在其中一个位置声明您的转换器资源。例如:

<UserControl
    x:Class="TestSO39734815UwpResource.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestSO39734815UwpResource"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

  <UserControl.Resources>
    <local:FirstNameToVisibilityConverter x:Key="FirstNameToVisibilityConverter"/>
  </UserControl.Resources>

  <Grid>
    <Grid.Resources>
      <p:Style TargetType="TextBox">
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
      </p:Style>
    </Grid.Resources>
    <StackPanel>
      <TextBlock Foreground="Red">HI</TextBlock>
      <TextBlock Foreground="Red" Text="THERE"/>
      <TextBox Foreground="Red" Text="{x:Bind FirstWord}"/>
      <TextBlock Foreground="Red" Text="{x:Bind SecondWord}"
                 Visibility="{x:Bind FirstWord, Converter={StaticResource FirstNameToVisibilityConverter}}"/>
      <CheckBox Foreground="Red" Content="Click me to hide the first word" IsChecked="{x:Bind FirstWordChecked}"/>
    </StackPanel>
  </Grid>
</UserControl>

另一种选择是将资源放在 App.xaml 文件中的 &lt;Application.Resources/&gt; 元素中,或者当然使用 {Binding} 扩展名,这确实会通过正常的资源查找过程。


附录:

就个人而言,我觉得这是平台中的一个错误。生成的代码隐藏无论如何都会访问框架元素,因此提供一个像基于运行时的{Binding} 那样遍历树的实现应该不难。某种程度的限制是可以理解的,但是像这样的任意不一致只会让 WPF 技能更难转移到 Winrt/UWP。

因此,我继续在 Connect 站点上打开了一个错误:x:Bind doesn't find converter resource。我猜微软会不同意,但至少如果我们幸运的话,他们会 a) 为实施决策提供一些理由,并且 b) 更改 the documentation 以便清楚地指出这个限制。

【讨论】:

  • 感谢彼得指出这一点,我完全同意这似乎有问题。一方面,我们现在与 x:Bind 有更紧密的对象耦合,但反过来我们必须全局声明资源?伤脑筋。
  • 彼得,您能否更新您的答案以显示 Converter={StaticResource ResourceKey=FirstNameToVisibilityConverter}}。我需要 ResourceKey= 让它工作
  • @Sean:我发布的代码是直接从工作项目中复制/粘贴的。您必须明确指定ResourceKey=,这很奇怪,但我向您保证,应该有一种方法可以让您的代码在没有它的情况下正常工作。不幸的是,我不能确定为什么它不适用于您的情况。重要的是要注意 Stack Overflow 的答案只需要有用;一个正确的答案最终具有逐字问题作者最终使用的代码并不是必需的(甚至不一定是一个好主意)。如果代码实际上是有效的,则最好使用更惯用的代码。
  • 好吧,现在我再次删除了它,它似乎可以按预期编译。我没疯。或者不知道我是。
  • @Sean:你没疯。至少可以说,Visual Studio 中的 XAML 东西(设计器、编译器)有点“古怪”。 “幽灵”错误来来去去;有时它们只是因为一个错误而需要重新启动 Visual Studio。其他时候,它们与编辑器不能很好地处理的设计时状态有关(例如,会报告错误,但代码仍然可以编译和运行)。我仍然希望,随着微软基本上放弃智能手机,他们会将注意力转移到 WPF 上,并更加努力地改善那里的开发者体验。
猜你喜欢
  • 1970-01-01
  • 2012-05-16
  • 2013-05-16
  • 2017-11-07
  • 2011-10-21
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 2013-06-30
相关资源
最近更新 更多