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

Wpf 自定义控件主题在重建时消失,wpf,custom-controls,Wpf,Custom Controls,我正忙于构建自定义控件。该主题有一个Generic.xaml,它由位于Generic文件夹中的合并字典引用2个资源字典(1-Generic brush和2-ControlTemplate)组成 我在解决方案中添加了一个tester项目(标准窗口)来测试控件 问题: 当我第一次添加控件时,控件的外观看起来是正确的。但是,当我对控件进行一些更改并重建它时,控件将从窗口中消失,我必须卸载窗口项目并重新加载它,以使控件的外观再次出现 当我运行调试器时,控件确实正确显示-只是在设计模式下,它变得很难使用

我正忙于构建自定义控件。该主题有一个Generic.xaml,它由位于Generic文件夹中的合并字典引用2个资源字典(1-Generic brush和2-ControlTemplate)组成

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

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

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

对于这种情况,是否有一种解决方案/解决方法,不涉及每次重建时卸载和重新加载窗口

编辑 我已经运行了一个测试,在该测试中,我将来自不同资源字典的所有信息复制到Generic.Xaml中,并注释掉了合并字典。问题似乎不在于MergeDictionary操作,因为问题仍然存在,但可能在于ComponentResourceKey/或静态属性。例如,我的一个ResourceDictionary包含以下内容

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

我猜看到主题工作有时意味着上述方法没有错,VS处理控件重建的方式也有问题。但我不明白的是,为什么VS既不能识别旧值,也不能识别新值,相反,它会忽略链接到ComponentResourceKey-Ps的所有值。在运行时,该控件可以完美地工作。

我这里似乎有3个选项

  • 使用我一直使用的方法:

    • 在C#类中定义ComponentResourceKey

    • 在资源字典中分配密钥

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

      <Setter Property="BorderBrush" Value="{DynamicResource {x:Static keys:Normal.BorderBrushKey}}"/>
      
      
      
    这样做的好处是,当您有多个主题要分配和使用时,资源键似乎过于简单,而且在Intellience的帮助下,在名称上键入错误的几率会降低。
    缺点是,当您处理一个大型项目时,您对控件进行了一个小的调整—没有加载任何ComponentResourceKey,并且您的项目在设计时看起来完全没有外观。要解决此问题,必须重新启动VS或卸载使用控件的项目,然后再次重新加载。Ps这只是在设计时。运行项目将给出正确的结果。这在VS中是一个愚蠢的问题

  • 返回到在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#类来保存所有ResourceKey 缺点是,您必须记住每个ResourceId的ResourceId名称,并按定义将其键入。在具有多个主题的控件中使用此选项也会令人沮丧

  • 使用上述2种混合物,即

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

    • 您可以按照方法2分配ResourceKey。但是ResourceId是C#类中指定的“text”字段,而不是x:static方法,即

      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
      
      公共静态类正常
      {
      静态ComponentResourceKey_background=新的ComponentResourceKey(typeof(G2ListBox),“Normal.background”);
      公共静态组件ResourceKey背景密钥
      {get{return}背景;}
      }
      //分派
      //因此,正常。背景和非关键点:正常。背景!!其中keys=引用到C#类
      
    • 然后使用

      <Setter Property="Background" Value="{DynamicResource {x:Static keys:Normal.BackGroundKey}}"/>
      //i.e we now can reference the C# class and have intelisence
      
      
      //i、 e我们现在可以参考C类并具有智能
      
    优点是1您有一个静态类,它保存了C#中的所有ResourceKey(这有点违背了无外观原理)。至少在使用端,您还可以访问适当的智能。但最棒的是VS在设计时工作得非常完美。 但是,这根本不会缩短赋值端,因此缺点仍然是需要键入详细文本才能为resourcekey指定颜色。有多个主题,每个主题都有自己的颜色集,这意味着您只能稍微缩短控件的样式,使用这种方法似乎很愚蠢

  • 因此,如果您想要最好的解决方案,而不关心设计时的外观,我更喜欢选项1。 如果您更喜欢设计时的视觉效果,那么我会选择方法2,除非您也必须在许多地方定义样式,那么选项3就足够了。 或者创建设计时资源字典和编译时资源字典。其中使用了设计时方法3和编译时方法2->不确定如何自动执行此操作。我通过使用合并字典来实现这一点,并在控件准备编译时取消对适当字典的注释,并删除designtime ResourceDictionary


    希望这有助于某人,因为有一天我不得不花一整天的时间来解决这个问题(我原以为我的控制有问题——结果发现VS有问题)。

    您是否尝试重新构建?不删除和添加项目?是。我只调整控件的一些值。在项目(控件)上单击鼠标右键,然后重新生成。我也在窗口上执行相同的操作(即右键单击“项目”并重建)。仅此而已,似乎“主题”消失了。我发现解决这个问题的唯一方法是卸载窗口并重新加载窗口项目-希望有更好的解决方案。我在日常工作中从不使用designer,你可以发现疑难解答陡坡非常有用designer确实有缺陷。我在几个项目中遇到了相同的问题<代码>合并
    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