2013-07-22 14 views
9

Visual Studio 2010 | .NET/WPF 4.0Il colore DynamicResource non funziona con BorderBrush su un bordo - Bug?

Penso che questo potrebbe essere un bug WPF, ma non riesco a trovare un bug report su di esso. Per coprire la possibilità che mi manca qualcosa di ovvio, mi rivolgo a StackOverflow per le risposte!

considerare questo XAML (nulla nel codebehind):

<Window x:Class="DownExpanders.BorderTest" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="BorderTest" Height="300" Width="300"> 
    <Window.Resources> 
     <Color x:Key="BackgroundColor" R="255" G="0" B="0" A="255"/> 
     <Color x:Key="BorderColor" R="0" G="0" B="255" A="255"/> 
     <SolidColorBrush x:Key="BorderColorBrush" Color="{DynamicResource BorderColor}"/> 
    </Window.Resources> 
    <Grid> 
     <Border BorderThickness="20"> 
      <Border.Background> 
       <SolidColorBrush Color="{DynamicResource BackgroundColor}"/> 
      </Border.Background> 
      <Border.BorderBrush> 
       <SolidColorBrush Color="{DynamicResource BorderColor}"/> 
      </Border.BorderBrush> 
     </Border> 

     <Border Margin="40" BorderBrush="{DynamicResource BorderColorBrush}" BorderThickness="20"/> 
    </Grid> 
</Window> 

Nella finestra di progettazione, rende come previsto. Il bordo esterno ha un grande bordo blu e uno sfondo rosso, il bordo interno ha un grande bordo blu. Grande.

Quando eseguo il codice, il bordo esterno non ha il bordo: sembra che non venga caricato. Lo sfondo è impostato su rosso correttamente. Nel frattempo, il bordo interno carica correttamente il suo bordo blu.

Se cambio "DynamicResource" su "StaticResource", viene eseguito correttamente il rendering durante l'esecuzione. L'incoerenza è davvero bugging me, e io non riesco a capire \

Quindi:.

  1. Perché il lavoro non DynamicResource per BorderBrush?
  2. Dato # 1, perché fa funziona per Sfondo?
  3. Perché la definizione esplicita del pennello a tinta unita nelle risorse sembra risolvere i problemi?

EDIT:

sembra che sia un bug che MS ha deciso di non fissare (grazie a Sheridan per il link): http://connect.microsoft.com/VisualStudio/feedback/details/589898/wpf-border-borderbrush-does-not-see-changes-in-dynamic-resource

+0

Interessante, accade ancora in .net 4.5.50760 quindi se si tratta di un bug non lo hanno ancora risolto. – Andy

+0

Sicuramente penseresti che sia un bug. Puoi anche aggiungere al tuo rapporto bug, Snoop riporta il pennello del bordo esterno come 'Trasparente' (Nessun errore) e questo problema non si verifica se hai impostato il pennello direttamente anche per il bordo esterno come in' BorderBrush = "{DynamicResource BorderColorBrush } "'. Quindi sembra più un problema di quando SolidColorbrush per BorderBrush è stato creato da un DynamicResource ** Color **, tutto diventa rovinato. Forse non è strano il caso di cercare di bloccare le risorse/accedervi – Viv

+1

oh qualcos'altro che ho visto anche io, se sposti le risorse ad un livello più alto, ad esempio "App.xaml", funziona bene per il tuo codice esatto – Viv

risposta

2

A quanto pare, la risposta alla tua domanda è no, questo comportamento è non un bug.

Questo problema è stato pubblicato sul sito Microsoft Connect da un utente e fu data la seguente risposta:

DynamicResources sono "alzò gli occhi" in fase di esecuzione piuttosto che di compilazione. Il "Dinamico" si riferisce a "non può essere aggiornato dinamicamente in qualsiasi momento" ma "lo cercheremo più tardi, quando è effettivamente necessario."

Se si desidera cambiare il pennello confine in fase di esecuzione, è necessario applicare una Name = "" attributo alla frontiera per toccare dal codebehind, oppure è possibile utilizzare una rilegatura per impostare il valore del pennello su a DependencyProperty (se si utilizza il pattern MVVM o qualcosa simile ).Modificare la proprietà e il pennello del bordo viene aggiornato dal sistema di rilegatura .

BTW, questa sarebbe stata una buona domanda su StackOverflow - "Perché non è la mia DynamicResource in fase di aggiornamento?"

Personalmente, mi piace l'ultima linea. Microsoft al suo massimo utile! La pagina può essere trovata here.

+2

Accetteremo la risposta da Microsoft se si tratta di un comportamento coerente. Lo sfondo viene caricato correttamente. Solo BorderBrush ha un problema. In effetti l'OP di quel bug ha notato la stessa cosa, e la risposta di MS è stata "non lo stiamo aggiustando". Bene merda, immagino ci sia la risposta. Assegnandoti il ​​segno di spunta per la ricerca del bug report: P – pfw

+0

Ho creato un semplice work-around: http://stackoverflow.com/questions/19427351/change-dynamicresource-color-value-during-runtime/19429175#19429175 –

2

Questo non sembra essere il caso con il RadialGradientBrush.

<Window x:Class="WpfApplication3.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 

    <Grid> 
     <Grid.Resources> 
      <Color x:Key="BackgroundColor" R="255" G="0" B="0" A="255"/> 
      <Color x:Key="BorderColor" R="0" G="0" B="255" A="255"/> 
      <SolidColorBrush x:Key="BorderColorBrush" Color="{DynamicResource BorderColor}"/> 
     </Grid.Resources> 
     <Border BorderThickness="20"> 
      <Border.BorderBrush> 
       <RadialGradientBrush> 
        <GradientStop Color="{DynamicResource BorderColor}"/> 
        <GradientStop Color="{DynamicResource BorderColor}"/> 
       </RadialGradientBrush> 
      </Border.BorderBrush> 
      <Border.Background> 
       <SolidColorBrush Color="{DynamicResource BackgroundColor}"/> 
      </Border.Background> 
     </Border> 

     <Border Margin="40" BorderBrush="{DynamicResource BorderColorBrush}" BorderThickness="20"/> 

    </Grid> 
</Window> 

enter image description here

1

Un'altra cosa interessante è che non si verifica quando utilizzare un rettangolo al posto di un bordo.

<Rectangle StrokeThickness="20"> 
     <Rectangle.Stroke> 
      <SolidColorBrush Color="{DynamicResource BorderColor}"/> 
     </Rectangle.Stroke> 
     <Rectangle.Fill> 
      <SolidColorBrush Color="{DynamicResource BackgroundColor}"/> 
     </Rectangle.Fill> 
    </Rectangle> 
0

Sembra risolto in 4.5. Nel mio caso funziona su Windows 8, ma non funziona su Windows XP (che non ha .net 4.5).

0

Ecco un controllo personalizzato che è possibile utilizzare al posto del bordo. Risolve il problema con la proprietà BorderBrush. Usa rettangoli che funzionano come indica un'altra risposta. Si noti che questo controllo probabilmente non corrisponde alle prestazioni dell'utilizzo del controllo Border ma funziona, quindi suggerisco di utilizzarlo solo dove necessario.

<Style TargetType="{x:Type controls:BorderFix}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type controls:BorderFix}"> 
       <DockPanel x:Name="PART_Container" 
          Background="{TemplateBinding Background}" 
          LastChildFill="True" 
          UseLayoutRounding="{TemplateBinding UseLayoutRounding}"> 
        <Rectangle x:Name="PART_LeftBorder" 
           DockPanel.Dock="Left" 
           Fill="{TemplateBinding BorderBrush}" 
           Width="{Binding Path=BorderThickness.Left, RelativeSource={RelativeSource TemplatedParent}}"/> 
        <Rectangle x:Name="PART_TopBorder" 
           DockPanel.Dock="Top" 
           Fill="{TemplateBinding BorderBrush}" 
           Height="{Binding Path=BorderThickness.Top, RelativeSource={RelativeSource TemplatedParent}}"/> 
        <Rectangle x:Name="PART_RightBorder" 
           DockPanel.Dock="Right" 
           Fill="{TemplateBinding BorderBrush}" 
           Width="{Binding Path=BorderThickness.Right, RelativeSource={RelativeSource TemplatedParent}}"/> 
        <Rectangle x:Name="PART_BottomBorder" 
           DockPanel.Dock="Bottom" 
           Fill="{TemplateBinding BorderBrush}" 
           Height="{Binding Path=BorderThickness.Bottom, RelativeSource={RelativeSource TemplatedParent}}"/> 
        <ContentPresenter x:Name="PART_Content"/> 
       </DockPanel> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

public sealed class BorderFix : ContentControl 
{ 
    static BorderFix() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(BorderFix), new FrameworkPropertyMetadata(typeof(BorderFix))); 
    } 
} 

Il fatto che dobbiamo farlo è piuttosto ridicolo. Un'altra risposta suggerisce che questo bug è stato risolto nella versione di .NET utilizzata da Windows 8. Non l'ho ancora testato, ma speriamo sia corretto. .NET 4.5.51209 presenta lo stesso problema.