我正在忙着构建自定义控件。主题有一个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的所有值。在运行期间,控件可以正常工作。
答案 0 :(得分:0)
好像我在这里有3个选项。
使用我一直使用的方法:
在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中是个愚蠢的问题!!
返回在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名称,并在定义时键入它。在具有多个主题的控件中使用它也会令人沮丧。
使用上述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分配颜色。拥有多个主题,每个主题都有自己的一组颜色,这意味着您只需稍微缩短控件的样式,并且使用此方法似乎很愚蠢
因此,如果你想要最好的解决方案而不关心设计时间,我宁愿选择1。 如果您更喜欢设计时视觉效果,那么除非您必须在多个地方定义样式,否则我会选择方法2,然后选项3就足够了。 或者创建一个设计时ResouceDictionary和一个编译时ResourceDictionary。在设计时使用方法3并且编译时方法2 - &gt;不知道如何自动执行此操作。我这样做是通过使用Merged Dictionaries,并在Control准备好编译时取消注释正确的字典,并删除设计时ResourceDictionary。
希望这对某人有所帮助,有一天因为我不得不花费一整天的时间来解决这个问题(我认为我的控制有问题 - 结果证明VS有问题)。