更新使用Static属性的元素的视觉效果
我使用SystemParameters.WindowGlassColor
更改TabItems
一堆的Foreground
,但wpf无法检测到具有该静态值的颜色更改。更新使用Static属性的元素的视觉效果
<Setter Property="Foreground"
Value="{Binding Source={x:Static SystemParameters.WindowGlassColor},
Converter={StaticResource WindowColorToForegroundConverter}}"/>
转换器检测颜色是否较暗或较亮并返回反转亮度画笔。此外,如果W10机器已关闭设置Show Color on Start, Taskbar, Action Center
(通过注册表)。
我可以通过SystemParameters.StaticPropertyChanged
检测颜色何时更改,但我无法更新Foreground
。
如何让我的应用程序知道窗口颜色的变化?
或
如何更新我的TabItems
的视觉效果?
我做到了!
我的目标是更新我TabItems
基于当前窗口的标题/铬色风格,不过由于Static
属性未触发我Triggers
,我不得不通过代码来做到这一点。
由于我的应用可以将镀铬扩展到客户区,因此在窗口颜色较暗时,某些Labels
可能难以阅读。
这是我的工作的结果是:
方法如下:我
使用StaticPropertyChanged
检测窗口颜色变化:
private void SystemParameters_StaticPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "WindowGlassColor")
{
RibbonTabControl.UpdateVisual();
}
}
我必须创建一个定制TabItem
控件,其中包含一个名为IsDark
的布尔属性。
我TabControl
有一个公共的方法来更新IsDark
值:
public static bool UsesColor
{
get
{
try
{
//Start menu:
//HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\
//CurrentVersion\Themes\Personalize
var autoColorization =
Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\DWM",
"ColorPrevalence", "0").ToString();
return autoColorization.Equals("1");
}
catch (Exception)
{
return false;
}
}
}
获取的给Color
亮度值:
public static int GetBrightness(this Color c)
{
//I discovered that 137 is the threshold, if more than that,
//the window title is white. Less than that, is black.
return (int)Math.Sqrt(
c.R * c.R * .241 +
c.G * c.G * .691 +
c.B * c.B * .068);
}
public void UpdateVisual()
{
//If glass isn't enabled, ignore.
var isDark = !SystemParameters.IsGlassEnabled
//Gets a registry value. See below.
|| !Glass.UsesColor
//Color threshold. See below.
|| SystemParameters.WindowGlassColor.GetBrightness() < 137;
//Manually update the IsDark property.
foreach (var tab in _tabPanel.Children.OfType<AwareTabItem>())
{
tab.IsDark = isDark;
}
}
如果Show Color on Start, Taskbar, Action Center
检查获取
最后,h ERE的我AwareTabItem
Style
:
<Style TargetType="{x:Type local:AwareTabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:AwareTabItem}">
<Grid Name="Panel" Background="Transparent">
<Border Name="ContentBorder" BorderBrush="#FFD4D4D4" BorderThickness="0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center" Effect="{x:Null}"
HorizontalAlignment="Center"
ContentSource="Header" Margin="10,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" SourceName="Panel">
<Setter Property="Foreground" Value="#FF2B579A" />
<Setter Property="Background" Value="#FFFAFAFA" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="#FFFAFAFA" />
<Setter Property="Foreground" Value="#FF2B579A" />
<Setter TargetName="ContentBorder" Property="BorderThickness" Value="1,1,1,0" />
</Trigger>
<!--When ExtendChrome, !IsDark, !IsSelected-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static prop:Settings.Default}, Path=EditorExtendChrome, FallbackValue=False}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsDark}" Value="False"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelect}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter TargetName="ContentBorder" Property="Background">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Color="#9AFFFFFF" Offset="0"/>
<GradientStop Color="#90FFFFFF" Offset="0.4"/>
<GradientStop Offset="1"/>
</RadialGradientBrush>
</Setter.Value>
</Setter>
</MultiDataTrigger>
<!--When ExtendChrome, !IsDark, IsMouseOver-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static prop:Settings.Default}, Path=EditorExtendChrome, FallbackValue=False}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsDark}" Value="False"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="#FF2B579A"/>
</MultiDataTrigger>
<!--When ExtendChrome, !IsDark, IsSelected-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static prop:Settings.Default}, Path=EditorExtendChrome, FallbackValue=False}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsDark}" Value="False"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="Panel" Property="Background" Value="#FFFAFAFA" />
<Setter Property="Foreground" Value="#FF2B579A" />
<Setter TargetName="ContentBorder" Property="BorderThickness" Value="1,1,1,0" />
</MultiDataTrigger>
<!--When ExtendChrome, IsDark, !IsSelected-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static prop:Settings.Default}, Path=EditorExtendChrome, FallbackValue=False}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsDark}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="#FFF8F8FF"/>
<Setter TargetName="ContentBorder" Property="Background">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Color="{Binding Source={x:Static SystemParameters.WindowGlassColor},
Converter={StaticResource ColorToAlphaConverter}, ConverterParameter=6E}" Offset="0"/>
<GradientStop Color="{Binding Source={x:Static SystemParameters.WindowGlassColor},
Converter={StaticResource ColorToAlphaConverter}, ConverterParameter=50}" Offset="0.4"/>
<GradientStop Offset="1"/>
</RadialGradientBrush>
</Setter.Value>
</Setter>
</MultiDataTrigger>
<!--When ExtendChrome, IsDark, IsMouseOver-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static prop:Settings.Default}, Path=EditorExtendChrome, FallbackValue=False}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsDark}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="#FFBFEFFF"/>
</MultiDataTrigger>
<!--When ExtendChrome, IsDark, IsSelected-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static prop:Settings.Default}, Path=EditorExtendChrome, FallbackValue=False}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsDark}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="Panel" Property="Background" Value="#FFFAFAFA" />
<Setter Property="Foreground" Value="#FF2B579A" />
<Setter TargetName="ContentBorder" Property="BorderThickness" Value="1,1,1,0" />
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--Default Values-->
<Setter Property="FontFamily" Value="Segoe UI Semilight"/>
</Style>
我注意到,使用深色窗口颜色时,黑色RadialGradientBrush
有一个奇怪的效果,所以我使用的实际窗口的颜色,使柔和的背景(以提高可读性当窗口太透明时)。要使用GradientStop
我必须创建一个Converter
,它取当前窗口的颜色并将给定的参数作为alpha值。
ColorToAlpha转换器:
您可以结合的目的,你明确你的'StaticPropertyChanged'事件处理程序设置创建一个新的属性,或者你可以使用['BindingExpression.UpdateTarget()' ](https://msdn.microsoft.com/en-us/library/system.windows.data.bindingexpression.updatetarget(v = vs.110).aspx)在事件处理程序中的方法。要么应该工作正常。你有什么?如果您仍然需要帮助,请提供一个很好的[mcve],显示您尝试过的内容,并解释您需要帮助的具体内容。 –
这篇文章包含了迄今为止我尝试过的所有内容。我不知道如何继续。我不知道如何根据不会自行更新的'Static'值来更新Foreground。 –