WinRT信息:找不到具有给定密钥的资源。转换器参考问题

时间:2016-09-27 21:45:20

标签: c# wpf uwp

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

1 个答案:

答案 0 :(得分:6)

这是因为您使用编译时绑定扩展{x:Bind}而不是运行时绑定扩展{Binding},并结合XAML编译器处理{{1作为特殊情况的属性,生成用于查找转换器的显式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

另一种替代方法是将资源放在App.xaml文件中,放在<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> 元素中,或者当然使用<Application.Resources/>扩展名,这会通过正常的资源查找过程


附录:

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

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