WinRT信息:找不到给定键的资源。转换器引用存在问题

4
我在启动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();
        }
    }  
}

我没有看到代码有任何问题。你在转换器中尝试过断点吗?看看是否被触发了? - AVK
NVM。但是你尝试将 {x:Bind} 更改为 {Binding} 看看是否有效吗?{x:Bind} 是编译时绑定,而 {Binding} 是运行时绑定。 - AVK
1个回答

11
这是因为您正在使用编译时绑定扩展 {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文件中的<Application.Resources/>元素中,或者当然也可以使用{Binding}扩展,它会经过正常的资源查找过程。


补充:

个人认为这是平台中的一个错误。生成的代码后台已经访问了框架元素,因此应该很容易提供一个实现,使其像运行时的{Binding}一样遍历树形结构。某种程度上的限制是可以理解的,但这种任意不一致性只会使将WPF技能转移到Winrt/UWP更加困难。

因此,我已经在Connect网站上开了一个漏洞:x:Bind doesn't find converter resource。我猜微软可能会持不同意见,但至少如果我们很幸运,他们会a)为实现决策提供一些理由,并且b)更改文档,以明确说明这个限制。


感谢你指出这个问题,Peter。我非常同意这似乎有点错误。一方面,我们现在使用x:Bind实现了更紧密的对象耦合,但另一方面,我们还需要全局声明资源??这真是让人头疼。 - Sean
Peter,请问你能否更新一下你的答案,将Converter={StaticResource ResourceKey=FirstNameToVisibilityConverter}}显示出来。我需要ResourceKey=来使其正常工作。 - Sean
@Sean:我发布的代码是从一个正在运行的项目中复制/粘贴而来的。你需要明确指定“ResourceKey =”可能有些奇怪,但我向你保证,应该有一种方法可以让你的代码在不使用它的情况下正常工作。不幸的是,我无法确定为什么在你的情况下它不能正常工作。需要注意的是,Stack Overflow的答案只需要有用即可;一个正确的答案不一定要与问题作者最终使用的代码完全相同,这甚至可能不是一个好主意。如果代码实际上是有效的,则更符合习惯的代码更可取。 - Peter Duniho
好的,现在我再次将其删除后,它似乎按预期编译。我不是疯了。或者说我不知道自己是否疯了。 - Sean
@Sean:你并不是疯了。在Visual Studio中,XAML相关的东西(设计师、编译器)有点“古怪”,这还不够形容。有时会出现“幽灵”错误,有时只是因为一个bug,需要重新启动Visual Studio。其他时候,它们与编辑器无法很好地处理的设计时状态有关(例如,会报告错误,但代码仍然可以编译和运行)。我仍然希望微软放弃智能手机后,他们会把重心转回WPF,并努力改善开发者的体验。 - Peter Duniho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接