我会倾向于这样处理:
- 将每个网格颜色设为单独的资源,然后使用 DynamicResource 从网格样式中引用它们。
- 将这些放在 Styles.xaml 中的单独“颜色”ResourceDictionary 中(在 ResourceDictionary.MergedDictionaries 下)
- 定义一个具有 Color 属性的 ColorProxy 对象,该属性在设置后会更新 ResourceDictionary 中画笔的颜色
- 在设置页面的构造函数中,克隆“colors”ResourceDictionary并为每种颜色构造一个ColorProxy,然后绑定它们
- 在设置页面的“保存”按钮中,将“colors”ResourceDictionary 复制到您的用户设置存储区以及主“colors”ResourceDictionary
大部分内容都很简单,所以我不会详细介绍。
这是 Styles.xaml 的想法:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<SolidColorBrush x:Key="Row Background Color" Color="..." />
...
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="DataGrid">
...
<Setter Property="Background" Value="{DynamicResource Row Background Color}" />
...
</Style>
</ResourceDictionary>
这里是复制构造 ColorProxy 对象的代码:
public IEnumerable<ColorProxy> ColorProxies
{
get
{
return
from key in _colorDict.Keys
select new ColorProxy { Dictionary=_colorDict, Key=key };
}
}
和 ColorProxy 本身:
public class ColorProxy
{
public ResourceDictionary Dictionary { get; set; }
public object Key { get; set; }
public Color Value
{
get { return ((SolidColorBrush)Dictionary[Key]).Color; }
set { Dictionary[Key] = new SolidColorBrush { Color = value }; }
}
}
现在可以使用以下方式编辑 ResourceDictionary 中的颜色:
<ItemsControl ItemsSource="{Binding ColorProxies}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="local:ColorProxy">
<DockPanel>
<TextBlock Text="{Binding Key}" Width="200" />
<ColorPicker Color="{Binding Color}" />
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
可以使用 XamlWriter 将编辑后的 ResourceDictionary 转换为用于存储的字符串,并使用 XamlReader 重新加载。
Styles.xaml 生成的主 ResourceDictionary 中的 MergedDictionaries 集合可以通过调用旧字典的 .Remove() 和新字典的 .Add() 来修改。
ResourceDictionaries 可以通过简单地构造一个新的 ResourceDictionary 来复制旧字典中的条目并将它们添加到新字典中。
这种技术不必局限于编辑颜色。可以创建任何类型的代理对象,包括由绑定中的转换器处理数据转换的通用代理对象。