2016-03-04 23 views
5

Sono abbastanza nuovo per WPF ma esperto in .NET (Winforms). Sto cercando di manipolare lo stile di evidenziazione di una listbox per controllare il colore focalizzato e sfocato dell'oggetto selezionato. Ogni singolo tutorial su questo che ho trovato utilizza uno stile personalizzato per assegnare un nuovo valore a SystemColors.HighlightBrushKey e SystemColors.ControlBrushKey. Ma non sta funzionando. Dopo innumerevoli ore cercando di farlo funzionare, mi è venuto in mente che forse era collegato al sistema operativo. Lo stavo provando su un sistema Windows 10. Ho eseguito lo stesso identico codice su un'installazione di Windows 7, ed ecco, ha funzionato!WBox ListBox WPF in Windows 10

Quindi apparentemente il vecchio metodo non funziona in Windows 10 (almeno questo è quello che mi sembra). Qualcuno ha trovato un'alternativa? Alla fine della giornata, voglio solo che la listbox mantenga l'evidenziazione luminosa anche quando non ha il focus. L'evidenziazione grigia predefinita è difficile da vedere e non sembra appropriata in alcuni casi. Ho uno scenario del mondo reale in cui ci si sente molto innaturali perché l'evidenziazione scompaia praticamente quando l'attenzione si allontana dal ListBox.

seguito è il codice XAML ho usato che funzionava su Windows 7 ma non su Windows 10. (Per inciso, ho anche provato a sostituire SystemColors.ControlBrushKey con SystemColors.InactiveSelectionHighlightBrushKey - i risultati erano gli stessi).

<Window x:Class="TestApp.TestWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:TestApp" 
     mc:Ignorable="d" 
     Title="TestWindow" Height="300" Width="300" Loaded="Window_Loaded"> 
    <Window.Resources> 
     <Style x:Key="myListboxStyle"> 
      <Style.Resources> 
       <!-- Background of selected item when focused --> 
       <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" /> 
       <!-- Background of selected item when not focused --> 
       <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Green" /> 
      </Style.Resources> 
     </Style> 
    </Window.Resources> 
    <Grid> 
     <ListBox x:Name="listBox" Style="{StaticResource myListboxStyle}" HorizontalAlignment="Left" Height="100" Margin="22,18,0,0" VerticalAlignment="Top" Width="237"> 
      <ListBoxItem>Test 1</ListBoxItem> 
      <ListBoxItem>Test 2</ListBoxItem> 
      <ListBoxItem>Test 3</ListBoxItem> 
     </ListBox> 
      <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="50,165,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/> 

    </Grid> 
</Window> 

risposta

5

Se davvero si vuole modificare le impostazioni predefinite per la vostra applicazione, si può sempre modificare lo stile facendo una copia del modello. In questo caso lo stile ListBoxItem.

Nella finestra di progettazione, fare clic su un oggetto ListBox, fare clic con il pulsante destro del mouse su Modifica modello e Modifica una copia.

Di seguito è riportato quello che ho ottenuto sul mio computer e uno screenshot dell'app in esecuzione con Red/Green che dimostra lo stile applicato agli elementi interessati. Si potrebbe naturalmente applicare questo a tutti gli elementi ...

<Window.Resources> 
    <Style x:Key="FocusVisual"> 
     <Setter Property="Control.Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
    <SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/> 
    <SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/> 
    <SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/> 
    <SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/> 
    <SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/> 
    <SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/> 
    <Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}"> 
     <Setter Property="SnapsToDevicePixels" Value="True"/> 
     <Setter Property="Padding" Value="4,1"/> 
     <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
     <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
     <Setter Property="Background" Value="Transparent"/> 
     <Setter Property="BorderBrush" Value="Transparent"/> 
     <Setter Property="BorderThickness" Value="1"/> 
     <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </Border> 
        <ControlTemplate.Triggers> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="IsMouseOver" Value="True"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/> 
          <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/> 
         </MultiTrigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="Selector.IsSelectionActive" Value="False"/> 
           <Condition Property="IsSelected" Value="True"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/> 
          <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/> 
         </MultiTrigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="Selector.IsSelectionActive" Value="True"/> 
           <Condition Property="IsSelected" Value="True"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/> 
          <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/> 
         </MultiTrigger> 
         <Trigger Property="IsEnabled" Value="False"> 
          <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
    <Style x:Key="ListBoxItemStyle2" TargetType="{x:Type ListBoxItem}"> 
     <Setter Property="SnapsToDevicePixels" Value="True"/> 
     <Setter Property="Padding" Value="4,1"/> 
     <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
     <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
     <Setter Property="Background" Value="Transparent"/> 
     <Setter Property="BorderBrush" Value="Transparent"/> 
     <Setter Property="BorderThickness" Value="1"/> 
     <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </Border> 
        <ControlTemplate.Triggers> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="IsMouseOver" Value="True"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/> 
          <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/> 
         </MultiTrigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="Selector.IsSelectionActive" Value="False"/> 
           <Condition Property="IsSelected" Value="True"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="Red"/> 
          <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/> 
         </MultiTrigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="Selector.IsSelectionActive" Value="True"/> 
           <Condition Property="IsSelected" Value="True"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="Green"/> 
          <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/> 
         </MultiTrigger> 
         <Trigger Property="IsEnabled" Value="False"> 
          <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

</Window.Resources> 

<Grid x:Name="LayoutRoot" Opacity="{Binding MainWindowOpacity}"> 
    <StackPanel> 
     <TextBlock Text="WPF" FontSize="36" Margin="20" Foreground="Orange" HorizontalAlignment="Center"/> 
     <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="237"> 
      <ListBoxItem Style="{DynamicResource ListBoxItemStyle1}">Test 1</ListBoxItem> 
      <ListBoxItem Style="{DynamicResource ListBoxItemStyle2}">Test 2</ListBoxItem> 
      <ListBoxItem>Test 3</ListBoxItem> 
     </ListBox> 
    </StackPanel> 
</Grid> 

e l'applicazione in azione:

ATTIVA:

Active

INATTIVO:

Inactive

Caveat emptor.

+0

Grazie Kory. Avevo già giocato con una soluzione simile alla tua (avevo già usato qualcosa del genere per personalizzare l'aspetto di un TreeView), ma le tue indicazioni mi davano i pezzi mancanti per ottenere esattamente quello che volevo. – Cosmicjive

+0

questo ha funzionato per me, deludendo il fatto che in Windows 10 funzioni così tanto ... – 00jt

0

Avevo un problema simile con lo stile di evidenziazione di ListBox in Windows 10 ... ancora la vecchia soluzione SystemColors.HighlightBrushKey e SystemColors.ControlBrushKey funzionava solo per me in Windows 7. Nel mio caso, volevo semplicemente rimuovere qualsiasi evidenziazione disegnata da WPF, quindi potrei sostituirla con la mia.

Per questo, ho semplicemente sostituito il ControlTemplate tramite il seguente stile breve nelle mie risorse:

 <Style TargetType="{x:Type ListBoxItem}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

Io generalmente piace sostituzione ControlTemplate verbose, ma questa era una soluzione concisa bello per me, sperando che potrebbe aiutare qualcuno altro.

3

Microsoft ha rotto questo per Windows 10, ma possiamo aggiustarlo!

Ecco ciò che il modello appare come in Windows 10 (solo le parti che mi interessa):

<ControlTemplate TargetType="{x:Type ListBoxItem}"> 
... 
     <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True"> 
      <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
     </Border> 
     <ControlTemplate.Triggers> 
      <MultiTrigger> 
       <MultiTrigger.Conditions> 
        <Condition Property="IsMouseOver" Value="True"/> 
       </MultiTrigger.Conditions> 
       <Setter Property="Background" TargetName="Bd" Value="#1F26A0DA"/> 
       <Setter Property="BorderBrush" TargetName="Bd" Value="#A826A0DA"/> 
      </MultiTrigger> 
      <MultiTrigger> 
       <MultiTrigger.Conditions> 
        <Condition Property="Selector.IsSelectionActive" Value="False"/> 
        <Condition Property="IsSelected" Value="True"/> 
       </MultiTrigger.Conditions> 
       <Setter Property="Background" TargetName="Bd" Value="#3DDADADA"/> 
       <Setter Property="BorderBrush" TargetName="Bd" Value="#FFDADADA"/> 
      </MultiTrigger> 
      <MultiTrigger> 
       <MultiTrigger.Conditions> 
        <Condition Property="Selector.IsSelectionActive" Value="True"/> 
        <Condition Property="IsSelected" Value="True"/> 
       </MultiTrigger.Conditions> 
       <Setter Property="Background" TargetName="Bd" Value="#3D26A0DA"/> 
       <Setter Property="BorderBrush" TargetName="Bd" Value="#FF26A0DA"/> 
      </MultiTrigger> 
      <Trigger Property="IsEnabled" Value="False"> 
       <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
      </Trigger> 
     </ControlTemplate.Triggers> 
    </ControlTemplate> 

Privacy hanno codificato i valori per i colori, come "# 1F26A0DA".

in Windows 7, il modello integrato per ListBoxItems era:

  <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
... 
        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsSelected" Value="true"> 
          <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> 
          <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> 
         </Trigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="IsSelected" Value="true"/> 
           <Condition Property="Selector.IsSelectionActive" Value="false"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> 
          <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/> 
         </MultiTrigger> 
         <Trigger Property="IsEnabled" Value="false"> 
          <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
      </ControlTemplate> 

Quindi, in pratica Microsoft stava usando le risorse come "SystemColors.InactiveSelectionHighlightBrushKey" in Windows 7. Ma ora fatto in modo che non possiamo fallo senza sovrascrivere il modello; dal momento che sono hard-coded in tutti i valori.

Quindi, per applicare la patch, è sufficiente sostituire il modello per ListBoxItem nel file App.Xaml; in modo che tutto ottenga la patch.

<Style TargetType="{x:Type ListBoxItem}"> 
     <Style.Resources> <!-- Use your own colors here if you want, or do it per class -->  
      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#FFFFA500"/> 
      <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey }" Color="#FFFFA500"/> 
     </Style.Resources> 

     <Setter Property="Template"> 
<!-- Revert the Template in Windows 10 to match the Windows 7 template that used "SystemColors.HighlightBrushKey" and such--> 
       <Setter.Value> 
       <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsSelected" Value="true"> 
          <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> 
          <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> 
         </Trigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="IsSelected" Value="true"/> 
           <Condition Property="Selector.IsSelectionActive" Value="false"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> 
          <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/> 
         </MultiTrigger> 
         <Trigger Property="IsEnabled" Value="false"> 
          <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 

       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
0

Ho paura che non ho un modo per testare questa operazione in Windows 10 specificamente, ma mi sono imbattuto in un problema simile solo su Windows 7. Definire il "ControlBrushKey" nelle risorse solo wasn' t lavorando.

Impostazione "InactiveSelectionHighlightBrushKey" ha lavorato per me:

<ListBox.Resources> 
    <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="DodgerBlue" /> 
</ListBox.Resources> 

Dodger blu è molto stretta corrispondenza alla selezione Aero di default; è solo un pelo più scuro. Sto ancora lavorando per capire come mapparlo al valore di selezione effettivo piuttosto che a un colore specifico.