我有四个滑块使用转换器设置Color
的RGBA通道值,如下所示:
<Slider Width="200" x:Name="redSlider" Minimum="0.0" Maximum="1.0"
Value="{Binding NewColor, Converter={StaticResource colorChannelConverter}, ConverterParameter ='R'}"/>
转换器代码:
public class ColorChannelConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var c = (Color)value;
var p = (string)parameter;
double channel = 0.0;
switch(p)
{
case "R":
channel = c.R;
break;
case "G":
channel = c.G;
break;
case "B":
channel = c.B;
break;
case "A":
channel = c.A;
break;
}
return channel / 255.0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// I'd like to do something like:
// var d = (byte)((double)value*255);
// if((string)parameter == "R") NewColor.R = d;
// item for other channels
// return NewColor;
// Note that I don't want to touch NewColor's other channels!
throw new NotImplementedException();
}
}
如您所见,现在获取频道非常简单。但是,转换器无法访问NewColor
属性,因此可以设置其各自的通道。如何在不使用另一个可以收集四个滑块值的控件的情况下执行此操作?
答案 0 :(得分:1)
您实际上只想绑定到颜色的单个组件,而不是绑定到整个颜色,例如MyColor.R
。问题是内置的Color
结构是不可观察的,因此视图不会正确更新。
我在一个颜色选择器应用程序中解决同样问题的方法是创建一个自定义类来表示我实现ObservableColor
并具有可观察属性的颜色(我称之为INotifyPropertyChanged
)对于各个颜色通道。在内部,它使用System.Windows.Media.Color
作为存储,并将其公开为应用程序中需要显示颜色的其他部分的属性。
这是我的意思的一个例子:
class ObservableColor : INotifyPropertyChanged
{
private Color mColor;
public Color Color
{
get { return mColor; }
set
{
// Update mColor and fire property change notifications for "Color"
// and for all of the individual channel properties
}
}
public byte A
{
get { return mColor.A; }
set
{
// Update mColor.A and fire property change notifications for "Color" and "A"
}
}
public byte R
{
// Same as A, but for the R color channel
}
// etc.
}
使用这样的内容可以绑定到NewColor.R
而不是NewColor
。这样你的转换器只需要返回该通道的值而不是返回整个颜色(正如你所发现的那样,它无法知道)。