自定义控件主题在重建时消失

时间:2014-02-13 11:08:06

标签: wpf custom-controls

我正在忙着构建自定义控件。主题有一个Generic.xaml,它包含一个引用2个资源字典的MergedDictionary(1 - Generic brush和2 - ControlTemplate),它位于Generic文件夹中。

我在解决方案中添加了一个测试项目(标准窗口)来测试控件。

问题: 当我第一次添加控件时 - 控件的外观看起来是正确的。然而,当我对控件进行一些更改并重建它时 - 控件从窗口中消失,我必须卸载Window项目并再次重新加载以使控件的外观再次出现。

当我运行调试器时,控件确实正确显示 - 它只是在设计模式下变得难以使用。

是否存在此事件的解决方案/解决方法,不涉及在每次重建时卸载和重新加载窗口?

修改

我已经运行了一个测试,我将所有信息从单独的资源字典复制到Generic.Xaml并注释掉了Merge Dictionary。似乎问题不在于MergeDictionary操作,因为问题仍然存在 - 但可能使用ComponentResourceKey /或静态属性。例如,我的一个ResourceDictionaries包含许多以下内容

<SolidColorBrush x:Key="{x:Static keys:Disabled.ForeGroundKey}" Color="Gray"/>

ForeGroundKey链接到静态类,例如:

public static class Normal
{
    static ComponentResourceKey _background = new ComponentResourceKey(typeof(G2ListBox),"ContainerBackground");
    public static ComponentResourceKey BackGroundKey
    { get { return _background; } }
}

我想看到主题工作有时意味着上述方法没有任何问题,并且VS处理控件重建的方式有问题。我不明白的是,为什么VS不识别旧值/新值,而是忽略链接到ComponentResourceKey-Ps的所有值。在运行期间,控件可以正常工作。

1 个答案:

答案 0 :(得分:0)

好像我在这里有3个选项。

  1. 使用我一直使用的方法:

    • 在C#Class中定义ComponentResourceKey

      public static class Normal
      {
          static ComponentResourceKey _background = new ComponentResourceKey(typeof(G2ListBox), "Normal.Background");
      
          public static ComponentResourceKey BackGroundKey
          { get { return _background; } }
      }
      
    • 在资源字典中指定密钥

      <SolidColorBrush x:Key="{x:Static keys:Normal.BackGroundKey}" Color="Yellow"/>
      
    • 使用资源字典中的键:

      <Setter Property="BorderBrush" Value="{DynamicResource {x:Static keys:Normal.BorderBrushKey}}"/>
      

    优势在于,当您有多个主题要分配和使用时,资源键似乎过于简单,并且在知识的帮助下减少了在输入名称时出现错误的可能性。 缺点是,当您处理大型项目时,您对控件进行了一些小调整 - 没有加载ComponentResourceKeys,并且您的项目在设计时看起来完全没有外观。要解决此问题,必须重新启动VS或卸载使用您的控件的项目并重新加载它。 Ps仅在设计时。运行项目将给出正确的结果。这在VS中是个愚蠢的问题!!

  2. 返回在XAML中定义组件资源键的更详细的方法,即

    • 定义并分配resourceKey。

      <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:G2ListBox}, ResourceId=Normal.Background}" Color="Yellow"/>
      
    • 使用resourceKey:

      <Setter Property="BorderBrush" Value="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type local:G2ListBox}, ResourceId=Normal.Background}}"/>
      

    优势是VS现在每次都在设计时工作。此外,您不必创建单独的C#类来保存所有resourcekeys 缺点是您必须记住每个resourceId的ResourceId名称,并在定义时键入它。在具有多个主题的控件中使用它也会令人沮丧。

  3. 使用上述2的混合物,即

    • 您仍然在C#库中定义ResourceKey

    • 您按照方法2分配ResourceKey但是ResourceId是在C#类中分配的“文本”字段,而不是x:静态方法,即

      public static class Normal
      {
          static ComponentResourceKey _background = new ComponentResourceKey(typeof(G2ListBox), "Normal.Background");
      
          public static ComponentResourceKey BackGroundKey
          { get { return _background; } }
      }
      //To assign
      <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:G2ListBox}, ResourceId=Normal.Background}" Color="Yellow"/>
      //Thus Normal.Background and not Keys:Normal.Background!!  where keys = referenced to the C# Class
      
    • 然后使用

      <Setter Property="Background" Value="{DynamicResource {x:Static keys:Normal.BackGroundKey}}"/>
      //i.e we now can reference the C# class and have intelisence
      

    优点是1你有一个静态类,它包含C#中的所有ResourceKeys(略微违背了无形的哲学)。您至少在使用方面也可以获得适当的知识。但最重要的是VS在设计时完美无缺。 然而,这根本不会缩短分配方面,因此缺点是您需要输入详细文本以为resourcekey分配颜色。拥有多个主题,每个主题都有自己的一组颜色,这意味着您只需稍微缩短控件的样式,并且使用此方法似乎很愚蠢

  4. 因此,如果你想要最好的解决方案而不关心设计时间,我宁愿选择1。 如果您更喜欢设计时视觉效果,那么除非您必须在多个地方定义样式,否则我会选择方法2,然后选项3就足够了。 或者创建一个设计时ResouceDictionary和一个编译时ResourceDictionary。在设计时使用方法3并且编译时方法2 - &gt;不知道如何自动执行此操作。我这样做是通过使用Merged Dictionaries,并在Control准备好编译时取消注释正确的字典,并删除设计时ResourceDictionary。

    希望这对某人有所帮助,有一天因为我不得不花费一整天的时间来解决这个问题(我认为我的控制有问题 - 结果证明VS有问题)。