在想要封装行为的地方使用UserControl(或自定义控件)。这里的行为不仅指交互逻辑(例如具有自定义双击行为的列表框),还包括数据模型(例如显示Person详细信息的控件,因此需要PersonToDisplay属性)。与该UserControl特定的资源将存储在控件的资源字典中。在想要共享资源的地方使用ResourceDictionary。例如,如果您有一组画刷要在多个位置使用(并且希望有一个集中更新它们的中心位置),那么就可以使用ResourceDictionary。有些情况可以纯粹使用资源来实现,但是您可能仍然希望将其打包成控件,以便在使用时更容易理解。例如,如果您有一个按钮,当鼠标悬停在上面时会闪烁,您可能觉得让用户编写(和阅读)比(其中样式在AnnoyingButton.xaml资源字典中)更容易,即使整个过程实际上可能是通过模板和触发器完成的,并没有实际代码。在这种情况下,我倾向于创建一个控件,因为(a)如果我发现需要添加代码,则控件更加健壮,(b)它可以节省我编写ResourceDictionary.MergedDictionaries元素的时间。不过这是一个判断性的问题。
我的经验法则是:对于DataTemplates、ControlTemplates、Style和ValueConverters、TemplateSelectors等,请使用ResourceDictionaries,而对于大型视图(可视元素),请使用UserControls将其“切分”为多个部分,所有这些部分都使用您的ResourceDictionaries进行样式设置。ResourceDictionaries的问题在于,如果您将一个可视元素放入其中,则只能使用它一次,因为它在资源中实例化,因此如果您在不同的可视控件中使用它两次,则会出现“可视元素只能有一个父级”的异常。另一方面,DataTemplates、Styles和ControlTemplates可以同时作为工厂供许多控件使用-每个控件都有自己的实例化。ValueConverters和TemplateSelectors(只要注意不要在其中更改状态)可以被多个可视控件使用,因为它们本身不是可视元素,这使它们成为ResourceDictionary静态方法的完美候选者。希望这能稍微解释清楚一些。