"{DependencyProperty.UnsetValue}"不是"FocusVisualStyle"属性的有效值。

22

我遇到了一个奇怪的错误,一直在尝试调试但没有成功。

我已经创建了子类hwndhost来显示一些内容,在该类中有以下函数以设置全屏:

    private void SetFullScreen(bool enable)
    {
        if (enable)
        {
            fs = new Window();
            fs.ResizeMode = ResizeMode.NoResize;
            fs.WindowState = System.Windows.WindowState.Maximized;
            fs.WindowStyle = System.Windows.WindowStyle.None;
            fs.Topmost = true;
            fs.PreviewKeyDown += delegate(object sender, KeyEventArgs e) { 
                if (e.Key==Key.Escape)
                    FullScreen = false;
            };
            fs.Show();
        }
        else
        {
            fs.Close();
            fs = null;
        }
    }

在我的原型WPF应用程序中,这个代码运行得很好,但是当我在主应用程序中使用它时,当关闭窗口(按下Escape键)并进行fs.close()调用时,会出现以下错误:

'{DependencyProperty.UnsetValue}' 不是属性 'FocusVisualStyle' 的有效值。

奇怪的是,这种情况发生在窗口关闭后大约1500毫秒。我尝试将fs的FocusVisualStyle设置为null,但似乎不起作用。我的直觉是,它正在尝试聚焦到我的应用程序中另一个没有此属性的元素,但实际上我不知道!

谢谢!

编辑。问题出在我全屏按钮自定义设置的FocusVisualStyle上。我将其设置为{x:Null},问题就解决了。

6个回答

31

当样式指向一个不存在StaticResource时,就会发生这种情况。

下面的 XAML 代码出现了问题:

<Grid.Resources>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="Height" Value="{StaticResource StandardControlHeight}"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
    </Style>
</Grid.Resources>

错误信息为:

System.InvalidOperationException: ''{DependencyProperty.UnsetValue}' 不是属性 'Height' 的有效值。

当我添加了缺失的 StaticResource 后,问题得到解决。


一如既往,WPF 的异常信息并不是非常清晰。 - Aleksey Pavlov
1
或者,StaticResource 存在,但是被引用它的样式 没有找到 它。我刚刚添加了我的答案来说明这种情况。 - Muhammad Sulaiman

14

我猜测,当你关闭提到的窗口时,获取焦点的控件具有由你设置的自定义样式,其中不包括任何 FocusVisualStyle。

因此,为了进一步帮助你,你应该再解释一下:在关闭此窗口时会发生什么(或应该发生什么)?

哪种控件类型应该获得焦点?


一个切换按钮会启动全屏命令,所以我猜这会在返回时获得焦点。然而,稍后一个键盘命令(例如F12)可能会启动它,因此可以是任何具有当前焦点的元素。那个切换按钮具有自定义样式,我尝试将那个样式的FocusVisualStyle设置为{x:Null},但没有成功。 - DaveO
1
我撒谎了,它被设置在两个地方,删除第二个解决了问题,谢谢! - DaveO
4
读者提到,出现错误是因为在某个地方没有合并定义实际焦点样式的ResourceDictionary。XAML设计师对StaticResource引用没有抱怨。直到我以特定方式在运行时更改键盘焦点时才出现错误。 - Vimes

11

导致上述异常的另一种方法是在使用静态资源后声明它,例如在样式声明中。

错误示例

<Style TargetType="Label">
    <Setter Property="Foreground" Value="{StaticResource BlueAccent}"/>
</Style>

<SolidColorBrush x:Key="BlueAccent" Color="#22afed"/>

正确

<SolidColorBrush x:Key="BlueAccent" Color="#22afed"/>

<Style TargetType="Label">
    <Setter Property="Foreground" Value="{StaticResource BlueAccent}"/>
</Style>

当你有多个资源字典并且最终导致“奇怪”的后果时,你所描述的情况可能变得更加复杂,因此应该尽量避免(例如,请参考这个问题:https://dev59.com/f2sy5IYBdhLWcg3w0RQ5#8443351)。 - David

4

如果您通过谷歌搜索问题标题而到达这里:引发此异常的另一种方法是使用触发器,但忘记设置值。

例如:

<ControlTemplate.Triggers>
  <Trigger Property="IsEnabled">
    <Setter Property="Background" Value="Gray" />
  </Trigger>
</ControlTemplate.Triggers>

这会导致 XamlParseException 错误,其中内部异常显示:

'{DependencyProperty.UnsetValue}' 不是属性 'IsEnabled' 的有效值。

更正:

<ControlTemplate.Triggers>
  <Trigger Property="IsEnabled" Value="False">
    <Setter Property="Background" Value="Gray" />
  </Trigger>
</ControlTemplate.Triggers>

2
另一种情况是当声明了StaticResource,但在提及时未被看到
例如,在我的情况下:

'{DependencyProperty.UnsetValue}'不是属性'Background'的有效值。

发生在应用启动之前,在App.xaml.cs文件中的OnStartup方法中。
异常消息提到了Background属性,它告诉我们:
在某些情况下,该属性将使用StaticResource,但是由于某种原因,StaticResource没有被正确加载。
<Setter Property="Background" Value="{StaticResource xxx}" />

或者

Background="{StaticResource xxx}"

WPF开始在层次结构中查找xxx,如果找到类似的东西

<SolidColorBrush x:Key="xxx">yyy</SolidColorBrush>

如果找不到所需的内容,就会出现异常。

在我的情况下,我将样式放在了一个单独的项目中,像这样:

- SharedModule
    - SharedResources.xaml <---- this will be in App.xaml/MergedDictionaries 
        - MergedDictionaries
            - ButtonStyles.xaml <---- xxx was defined and used here
            - ToggleButtonStyles.xaml <--- xxx was used here as well

我认为在ToggleButtonStyles.xaml中的样式会看到xxx,因为声明的顺序(ButtonStyles.xaml在上面,在ToggleButtonStyles.xaml之前被合并),但事实证明这是错误的!

解决方案1.

DynamicResource替换StaticResource

<Setter Property="Background" Value="{DynamicResource xxx}" />

这样,如果xxx在启动时没有找到,WPF就不会抛出异常,但是它之后会像预期的那样使用它。
解决方案2:
将所有颜色提取到一个单独的ResrouceDictionary中,并在SharedResources.xaml之前在App.xaml中合并它。
- Application
    - App.xaml
        - ResourceDictionary
            - MergedDictionaries
                - Colors.xaml <--- xxx is defined one level above SharedResources/MergedDictionaries
                - SharedResources.xaml

1

这种异常的另一个原因可能是将属性值设置为错误的类型。例如,考虑以下XAML代码:

<Grid>
    <Grid.Resources>
        <sys:Double x:Key="DoubleWidth">200</sys:Double>
    </Grid.Resources>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{StaticResource DoubleWidth}"/> -> Exception here
    </Grid.ColumnDefinitions>
    <TextBlock Text="Abc"/>
</Grid>

在这段代码中,以ColumnDefinition开头的那一行会导致上述异常(ArgumentException: '200'不是属性“Width”的有效值)被抛出,因为ColumnDefinition.Width属性的类型不是System.Double值,而是System.Windows.GridLength结构体。 要解决此问题,首先在Grid.Resources块中定义一个新资源,如下所示:

<GridLength x:Key="GridLengthWidth">200</GridLength>

并将错误的行替换为以下行:
<ColumnDefinition Width="{StaticResource GridLengthWidth}"/>

实际上,当我们将属性设置为错误的类型时,Visual Studio会用下划线标出该属性并提示“The resource 'DoubleWidth' has an incompatible type”,但编译仍然会继续进行。


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