我正在尝试创建ShaderEffect
(非常成功),但是,我有一个问题是为他们正确实施IsEnabled
。
我希望让IsEnabled
动态启用/关闭效果,而不是更改元素的Effect
属性。主要是因为我在动画中绑定有问题(可以解释,如果有人坚持,IsEnabled
错误方式)和可用性(绑定到IsEnabled
比设置更容易Effect
)。
这是效果
public class SomeEffect : ShaderEffect
{
public Brush Input
{
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
public static readonly DependencyProperty InputProperty =
ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(SomeEffect), 0);
public bool IsEnabled
{
get { return (bool)GetValue(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.Register("IsEnabled", typeof(bool), typeof(SomeEffect), new PropertyMetadata(true, OnIsEnabledPropertyChanged));
private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != e.OldValue)
(d as SomeEffect).SetValue(IsEnabledPrivateProperty, (bool)e.NewValue ? 1.0 : 0.0);
}
private static readonly DependencyProperty IsEnabledPrivateProperty =
DependencyProperty.Register("IsEnabledPrivate", typeof(double), typeof(SomeEffect), new PropertyMetadata(1.0, OnIsEnabledPrivatePropertyChanged));
private static void OnIsEnabledPrivatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != e.OldValue)
(d as SomeEffect).SetValue(IsEnabledProperty, (double)e.NewValue != 0);
PixelShaderConstantCallback(0)(d, e);
}
private static PixelShader _shader = new PixelShader() { UriSource = new Uri("...", UriKind.Relative) };
public SomeEffect()
{
PixelShader = _shader;
UpdateShaderValue(IsEnabledPrivateProperty);
}
}
这是着色器
sampler2D _input : register(s0);
float _enabled : register(C0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(_input, uv);
if(_enabled == 0)
return color;
...
return somethingelse;
}
它做得非常愚蠢,总是调用着色器,但如果设置了IsEnabled
则不会做任何事情(返回原始颜色)。
有bool
属性有一个棘手的解决方法,着色器只能有double
,所以我实现了另一个依赖属性,然后由ShaderEffect
的服务函数使用(即, PixelShaderConstantCallback
和UpdateShaderValue
)。我可以使用转换器并具有double
属性,但最好让bool IsEnabled
直接在xaml中使用。
我尝试了什么:
PixelShader
属性设置为null
,这会导致服务功能失败,因为它们会将其初始化为null
。如果设置了某些绑定到效果的静态回调属性,而PixelShader == null
则会出现异常PresentationCore.dll中出现未处理的“System.InvalidOperationException”类型异常 附加信息:必须在ShaderEffect上设置PixelShader。
我是用上面解释的那种愚蠢的方式做到的。我对着色器知之甚少,但很明显,这种做法是错误的。但它确实有效。
我可以想到可以创建一个自定义控件,它将包含两个内容容器:有效(永远打开)和不带。更改此控件的IsEnabled
将将内容从一个容器移动到另一个容器。但即使没有开始,这看起来相当愚蠢和有限,虽然比以前的解决方案更优化(因为着色器不会被称为零大小或不可见的元素,我认为)。
那么,正确对IsEnabled
实施ShaderEffect
的方式是什么?