2013-07-18 82 views
6

检查以下情形(其他人可能也适用),你可以创建项目只需复印件粘贴在这里的代码在正确的文件]:Visual Studio WPF设计器中的错误?

一个 - 建立一个具有基本的东西(Resources.xaml)ResourceDictionary中:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <SolidColorBrush Color="Red" x:Key="Test" /> 

    <Style TargetType="{x:Type GroupBox}" x:Key="Test2" > 
     <Setter Property="Background" Value="Blue" /> 
    </Style> 

    <Style TargetType="{x:Type TextBlock}" > 
     <Setter Property="Foreground" Value="Green" /> 
    </Style> 
</ResourceDictionary> 

b - 创建用户控制基站在别人将继承含有基本资源(UserControlBase.cs):

using System.Windows.Controls; 
using System; 
using System.Windows; 

namespace ResourceTest 
{ 
    public class UserControlBase : UserControl 
    { 
     public UserControlBase() 
     { 
      this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("ResourceTest;component/Resources.xaml", UriKind.RelativeOrAbsolute) }); 
     } 
    } 
} 

ç - 创建一个用户控件从基部继承(UserControl1.xaml):

<ResourceTest:UserControlBase x:Class="ResourceTest.UserControl1" 

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:ResourceTest="clr-namespace:ResourceTest" 

      mc:Ignorable="d" 

      d:DesignHeight="300" 
      d:DesignWidth="300" > 
    <Grid> 
     <GroupBox BorderBrush="{StaticResource Test}" Margin="3" Header="Test" Style="{DynamicResource Test2}" > 
      <TextBlock Text="TESTTEST" /> 
     </GroupBox> 

    </Grid> 
</ResourceTest:UserControlBase> 

结果:StaticResources得不到解决(并没有加载测试BorderBrush)。 DynamicResources已解决(背景为蓝色),但设计人员说它无论如何都找不到资源(第一次工作正常,但是当您打开/关闭设计器时,资源无法解析)。非命名资源,如TextBlock样式工作正常。

这是一个设计师错误还是我做错了什么?在资源永不改变的场景中,必须声明资源为动态的吗?

enter image description here

在此先感谢。

+0

可以将资源声明为动态,只是效率不高。如果仅在此处使用此ResourceDictionary,是否尝试将它添加到基类的XAML前端中的'UserControl.Resources'中,以查看其行为是否有所不同? –

+0

@WillEddins:在我真正的应用程序中,资源被设置在一个基本的UserControl上,因此每个控件都有必要的资源,以便在WPF设计器上正确地看到它(否则这些样式仅应用于运行时,并且我们无法进行适当的UI设计,除非启动每次更改的应用程序:S)。 –

回答

1

看起来设计师在设计时在代码隐藏中解决MergedDictionaries问题似乎很困难。

通过将ResourceDictionary移动到Initialize之前可以看到一个更糟糕的例子。

public UserControl1() 
{ 
    this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("TempProject;component/Resources.xaml", UriKind.RelativeOrAbsolute) }); 
    InitializeComponent(); 
} 

在这种情况下,即使DynamicResource无法在设计时解决,说明设计时视图不一定调用构造函数,你可能期望。我使用Visual Studio 2012测试了此功能,因此此行为自2010年以来未发生变化。

根据您的原始测试代码,请注意StaticResource在运行时按预期成功绑定(出现红色边框),无论在设计时间视图中抛出的“错误”和缺少红色边框。

我看到两个选项:

  1. 使用DynamicResource在必要时在设计时解决这些。虽然您可以使用StaticResource,但相关的“错误”和缺乏设计时间视图显然是一个问题。 Other answers seem to indicate there may not be much performance difference之间现在两个。

  2. 只需在您的UserControl.Resources中实例化ResourceDictionary,并且不要从基类继承。在使用基类凝聚一些代码时,由于每次都要创建一个新的ResourceDictionary实例,因此效率不高。既然你不能(AFAIK)用XAML前端的基类扩展,你可能会反对在这个抽象层次上有一个未引用的MergedDictionary

+0

感谢您花费在此的时间。我们目前正在使用方法1,但我有点担心警告(即使它不伤害它不应该在那里)。解决方案2它不是一个选项,因为基类资源有点复杂(您可以在运行时更改应用程序的样式),因此涉及多个资源字典。为了让事情变得更加困难,我们希望在设计时看到控件,就像运行时一样,所以我们只在设计时添加资源缓存(否则它们来自应用程序)。这就是为什么我们创建了一个基本的UserControl ... –

+0

你认为我们应该向Ms提交一个bug吗? –

+0

@SoMoS我有兴趣听到一个更熟悉设计师如何在构造函数和任何方面工作的人。然而,就运行时改变样式而言,我通常希望在Application.Resources层次上看到一个'ResourceDictionary'的变化。即使您将示例中的ResourceDictionary定义为静态(因此在添加时共享它),您仍然需要按实例更改MergedDictionary,是不是?我相信你的实现是不同的,但似乎是一个复杂的方法去做。 –

相关问题