2016-02-29 2 views
0

Я использую SystemParameters.WindowGlassColor для изменения Foreground связки TabItems, но 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?

+0

Вы можете создать новое свойство с целью связывания, который явно установлен в вашем файле 'обработчик события StaticPropertyChanged', или вы можете использовать [' BindingExpression.UpdateTarget() ' ] (https://msdn.microsoft.com/en-us/library/system.windows.data.bindingexpression.updatetarget (v = vs.110) .aspx) в обработчике событий. Либо должно работать нормально. Что вы пробовали? Если вам по-прежнему нужна помощь, предоставьте хороший [mcve], который показывает, что вы пробовали, с объяснением того, что именно вам нужно. –

+0

Сообщение содержит все, что я пробовал до сих пор. Я не знаю, как это сделать. Я не знаю, как обновить Foreground на основе значения Static, которое не обновляется самостоятельно. –

ответ

1

Я сделал это!

Моя цель состояла в том, чтобы обновить стиль моей TabItems на основе текущего цвета заголовок окна/хром, но так как Static свойство не вызывая мое Triggers, я должен был сделать это с помощью кода.

Поскольку мое приложение может распространять хром в клиентскую область, некоторые Labels могут быть трудночитаемыми, а цвет окна темный.

Это результат моей работы:

Light: Light Theme

Dark: Dark Theme

Вот как:

Я обнаружить изменения окна цвета с помощью StaticPropertyChanged:

private void SystemParameters_StaticPropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "WindowGlassColor") 
    { 
     RibbonTabControl.UpdateVisual(); 
    } 
} 

Мне пришлось создать пользовательский элемент управления TabItem с одним булевым свойством, называемым IsDark.

Моего TabControl имеет публичный метод для обновления IsDark значения:

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 проверяется:

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); 
} 

И, наконец, h ERE в моей AwareTabItemStyle:

<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, который принимает текущий цвет окна и применяет данный параметр как альфа-значение.

ColorToAlpha конвертер:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    var color = value as Color?; 
    var alphaAux = parameter as string; 

    if (!color.HasValue) 
     return value; 

    if (String.IsNullOrEmpty(alphaAux)) 
     return value; 

    int alpha = 0; 
    if (!int.TryParse(alphaAux, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out alpha)) 
     return value; 

    return Color.FromArgb((byte)alpha, color.Value.R, color.Value.G, color.Value.B); 
} 
Смежные вопросы