C# 更改类绑定阴影颜色WPF
我正在研究如何在WPF文档中复制Google按钮的悬停阴影效果,结果发现:,这正好回答了我的问题,但我唯一的问题是我通常用XAML做所有前端工作,因此我对C#的样式设计不是很有经验。我的问题是,我想“绑定”我的前景色和阴影色,这是因为在代码中它只将其设置为灰色,这意味着我必须为我想要设置的每种颜色执行一个完整的其他类。这是我现在的代码: MainWindow.xaml:C# 更改类绑定阴影颜色WPF,c#,wpf,binding,styling,shadow,C#,Wpf,Binding,Styling,Shadow,我正在研究如何在WPF文档中复制Google按钮的悬停阴影效果,结果发现:,这正好回答了我的问题,但我唯一的问题是我通常用XAML做所有前端工作,因此我对C#的样式设计不是很有经验。我的问题是,我想“绑定”我的前景色和阴影色,这是因为在代码中它只将其设置为灰色,这意味着我必须为我想要设置的每种颜色执行一个完整的其他类。这是我现在的代码: MainWindow.xaml: <Button Content="shadow"> <Button.Style>
<Button Content="shadow">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="local:UI.Elevation" Value="10"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="local:UI.Elevation" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
用户界面:
public static class UI
{
public static readonly DependencyProperty ElevationProperty = DependencyProperty.RegisterAttached("Elevation", typeof(double), typeof(UI), new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender, null, OnRedElevationChanged));
public static double GetElevation(this UIElement element) => element.GetValue(ElevationProperty) as double? ?? default;
public static void SetElevation(this UIElement element, double elevation) => element.SetValue(ElevationProperty, elevation);
private static object OnRedElevationChanged(DependencyObject d, object value)
{
if (d is UIElement element && value is double elevation)
if (elevation == 0)
element.Effect = null;
else
{
Effect e = CreateElevation(elevation, element.Effect);
if (e != null)
element.Effect = e;
}
return value;
}
private static Effect CreateElevation(double elevation, Effect source)
{
void MixShadows(DropShadowEffect nearest, DropShadowEffect matched, double balance)
{
matched.BlurRadius = matched.BlurRadius * (1 - balance) + nearest.BlurRadius * balance;
matched.ShadowDepth = matched.ShadowDepth * (1 - balance) + nearest.ShadowDepth * balance;
}
DropShadowEffect[] shadows = new DropShadowEffect[]
{
new DropShadowEffect()
{
BlurRadius = 5,
ShadowDepth = 1
},
new DropShadowEffect()
{
BlurRadius = 8,
ShadowDepth = 1.5
},
new DropShadowEffect()
{
BlurRadius = 14,
ShadowDepth = 4.5
},
new DropShadowEffect()
{
BlurRadius = 25,
ShadowDepth = 8
},
new DropShadowEffect()
{
BlurRadius = 35,
ShadowDepth = 13
}
};
elevation = Math.Max(0, elevation / 12 * shadows.Length - 1);
int prevIndex = (int)Math.Floor(elevation), index = (int)elevation, nextIndex = (int)Math.Ceiling(elevation);
double approx = elevation - index;
DropShadowEffect shadow = shadows[index];
if (approx != 0)
MixShadows(approx < 0 ? shadows[prevIndex] : shadows[nextIndex], shadow, Math.Abs(approx));
bool modify = false;
if (source is DropShadowEffect sourceShadow)
{
sourceShadow.BlurRadius = shadow.BlurRadius;
sourceShadow.ShadowDepth = shadow.ShadowDepth;
shadow = sourceShadow;
modify = true;
}
shadow.Direction = 270;
shadow.Color = Colors.Red;
shadow.Opacity = .42;
shadow.RenderingBias = RenderingBias.Performance;
return modify ? null : shadow;
}
}
公共静态类UI
{
public static readonly dependencProperty ElevationProperty=dependencProperty.RegisterAttached(“高程”、typeof(双精度)、typeof(UI)、new FrameworkPropertyMetadata(默认值(双精度)、FrameworkPropertyMetadata.AffectsRender、null、OnRedeElevationChanged));
公共静态双GetElevation(此UIElement元素)=>element.GetValue(ElevationProperty)作为双???默认值;
公共静态void SetElevation(此UIElement元素,双立面)=>element.SetValue(ElevationProperty,立面);
私有静态对象OnRedElevationChanged(DependencyObject d,对象值)
{
如果(d为UIElement,元素值为双立面(&V))
如果(高程==0)
element.Effect=null;
其他的
{
效果e=CreateElevation(标高,元素效果);
如果(e!=null)
元素效应=e;
}
返回值;
}
专用静态效果CreateElevation(双立面,效果源)
{
void MixShadows(最近的DropShadowEffect,匹配的DropShadowEffect,双平衡)
{
matched.BlurRadius=matched.BlurRadius*(1-平衡)+最近的.BlurRadius*平衡;
matched.ShadowDepth=matched.ShadowDepth*(1-平衡)+最近的.ShadowDepth*平衡;
}
DropShadowEffect[]阴影=新的DropShadowEffect[]
{
新的DropShadowEffect()
{
半径=5,
阴影深度=1
},
新的DropShadowEffect()
{
半径=8,
阴影深度=1.5
},
新的DropShadowEffect()
{
半径=14,
阴影深度=4.5
},
新的DropShadowEffect()
{
半径=25,
阴影深度=8
},
新的DropShadowEffect()
{
半径=35,
阴影深度=13
}
};
标高=数学最大值(0,标高/12*阴影。长度-1);
int prevIndex=(int)数学地板(标高),index=(int)标高,nextIndex=(int)数学天花板(标高);
双近似值=高程-指数;
DropShadowEffect阴影=阴影[索引];
如果(大约!=0)
混合阴影(大约<0?阴影[prevIndex]:阴影[nextIndex]、阴影、数学Abs(大约));
bool-modify=false;
if(源为DropShadowEffect sourceShadow)
{
sourceShadow.BlurRadius=shadow.BlurRadius;
sourceShadow.ShadowDepth=shadow.ShadowDepth;
shadow=sourceShadow;
修改=真;
}
阴影方向=270;
shadow.Color=Colors.Red;
阴影.不透明度=.42;
shadow.RenderingBias=RenderingBias.Performance;
返回修改?空:阴影;
}
}
为了在XAML中得到我想要的东西,我会这样做:
<Button Content="shadow">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="local:UI.Elevation" Value="10"/>
<Setter Property="local:UI.Elevation.Foreground" Value="Blue"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="local:UI.Elevation" Value="0"/>
<Setter Property="local:UI.Elevation.Foreground" Value="Blue"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
但是我不太知道如何连接
local:UI.Elevation.Foreground
要更改阴影颜色,我必须从UI.cs
更改这一行:shadow.Color=Colors.Red代码>并将其绑定到立面。前景,但我遇到了困难。有人能帮忙吗?您只需使用名为Color
的Color
类型的新附加属性更新UI类,并为其指定您喜欢的默认颜色
然后,在其OnColorChanged
处理程序中,调用OnElevationChanged
,以便重新创建阴影
#region Color (Attached Property)
public static readonly DependencyProperty ColorProperty =
DependencyProperty.RegisterAttached(
"Color",
typeof(Color),
typeof(UI),
new PropertyMetadata(Colors.Black, OnColorChanged));
public static Color GetColor(DependencyObject obj)
{
return (Color)obj.GetValue(ColorProperty);
}
public static void SetColor(DependencyObject obj, Color value)
{
obj.SetValue(ColorProperty, value);
}
private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
OnElevationChanged(d, GetElevation((UIElement)d));
}
#endregion
在CreateElevation
方法中,为颜色添加一个新参数,以便进行设置
private static Effect CreateElevation(double elevation, Effect source, Color color)
{
...
shadow.Color = color;
...
}
最后,在OnElevationChanged
中更新它,以便调用GetColor
,以便它可以传入新的Color
属性
private static object OnElevationChanged(DependencyObject d, object value)
{
if (d is UIElement element && value is double elevation)
if (elevation == 0)
element.Effect = null;
else
{
Effect e = CreateElevation(elevation, element.Effect, GetColor(element));
if (e != null)
element.Effect = e;
}
return value;
}
示例XAML
<Button
Width="100"
Height="20"
Content="shadow">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="local:UI.Elevation" Value="10" />
<Setter Property="local:UI.Color" Value="Blue" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="local:UI.Elevation" Value="5" />
<Setter Property="local:UI.Color" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
注意:您可以进行一些重构,以使所有这些更干净,但希望这能让您开始。因此,我制作了一个DependencyProperty colorProperty
和一个OnColourChanged
事件,但我不明白如何将其发送到OnElevationChanged
,在那里我可以把它发送到CreateElevation
我用工作代码更新了我的答案。您可能应该投入一些时间来了解附加属性是如何工作的。这将帮助您更好地理解代码。通过附加的属性/行为,您可以做很多事情!:)工程伟大和预期!一定要研究附加属性和使用C#的更多前端设计。再次感谢!