使用转换器设置颜色的 RGBA 通道
Setting RGBA channels of Color using a Converter
我有四个滑块使用转换器设置 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
属性,因此它无法设置其各个通道。我怎样才能做到这一点而不使用另一个控件来收集四个滑块的值?
您实际上只想绑定到颜色的单个组件,而不是绑定到整个颜色,例如 MyColor.R
。问题是内置的 Color
结构不可观察,因此视图不会适当更新。
我在我正在处理的颜色选择器应用程序中解决这个相同问题的方法是创建一个自定义 class 来表示我的颜色(我称之为 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
。这样你的转换器只需要 return 该通道的值而不是 return 整个颜色(它无法知道,正如你发现的那样)。
我有四个滑块使用转换器设置 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
属性,因此它无法设置其各个通道。我怎样才能做到这一点而不使用另一个控件来收集四个滑块的值?
您实际上只想绑定到颜色的单个组件,而不是绑定到整个颜色,例如 MyColor.R
。问题是内置的 Color
结构不可观察,因此视图不会适当更新。
我在我正在处理的颜色选择器应用程序中解决这个相同问题的方法是创建一个自定义 class 来表示我的颜色(我称之为 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
。这样你的转换器只需要 return 该通道的值而不是 return 整个颜色(它无法知道,正如你发现的那样)。