2011-02-09 11 views
7

Abbiamo bisogno di fare in modo che alcune immagini grafiche vettoriali cambino il colore di alcuni elementi all'interno dell'immagine in fase di esecuzione. Sembrerebbe che l'impostazione di quei colori basati su valori di risorse statici o dinamici non funzionerebbe. Vogliamo avere più versioni della stessa grafica, ognuna con la possibilità di impostare determinati elementi grafici (Percorso, Linea, ecc.) A colori diversi, quindi non credo che un approccio basato su risorse dinamiche possa funzionare. Ciò lascia vincoli di dati che sembrano l'approccio giusto. Si aggiorna il grafico di utilizzare un'expr associazione dati, invece di un colore pennello hard-coded in questo modo:Come è possibile rendere dinamico il colore degli elementi di una WPF DrawingImage?

<DrawingImage x:Key="Graphic1"> 
    <DrawingImage.Drawing> 
    <DrawingGroup> 
     <DrawingGroup.Children> 
     <GeometryDrawing Geometry="F1 M 8.4073,23.9233L"> 
      <GeometryDrawing.Pen> 
      <Pen LineJoin="Round" Brush="{Binding Line1Brush, Mode=OneWay}"/> 
      </GeometryDrawing.Pen> 
     </GeometryDrawing> 
     <GeometryDrawing Geometry="F1 M 3.6875,2.56251L"> 
      <GeometryDrawing.Pen> 
      <Pen LineJoin="Round" Brush="{Binding Line2Brush, Mode=OneWay}"/> 
      </GeometryDrawing.Pen> 
     </GeometryDrawing> 
     </DrawingGroup.Children> 
    </DrawingGroup> 
    </DrawingImage.Drawing> 
</DrawingImage> 

viene creato un oggetto vista del modello (sostenere INotifyPropertyChanged) istanza per ogni istanza di Graphic1 in questo caso e fare sicuro che sia sia una proprietà Line1Brush sia una Line2Brush. Sembra buono, ma non riesco a farlo funzionare. Presumo che questo grafico, che è a sua volta definito in un dizionario di risorse per oggetti immagine e tento di impostare il loro DataContext e ottengo l'output di errore di associazione dati nella mia finestra di debug. Ecco il codice XAML Image:

<Image x:Name="Pulse1" Grid.Column="0" Source="{StaticResource Graphic1}"/> 
<Image x:Name="Pulse2" Grid.Column="1" Source="{StaticResource Graphic1}"/> 

E poi nel metodo della finestra Initialize ho impostato il loro contesto dati in questo modo:

public MainWindow() 
{ 
    InitializeComponent(); 
    this.DataContext = this; 
    this.PulseImage1 = new PulseImageViewModel(); 
    this.PulseImage2 = new PulseImageViewModel(); 
    this.PulseImage2.Line1Brush = Brushes.Green; 
    this.PulseImage2.Line2Brush = Brushes.Red; 
    this.Pulse1.DataContext = this.PulseImage1; 
    this.Pulse2.DataContext = this.PulseImage2; 
} 

Dove PulseImageViewModel (vedi sotto) definisce due proprietà Line1Brush e Line2Brush, ognuno dei quali attiva l'evento PropertyChanged.

public class PulseImageViewModel : INotifyPropertyChanged 
{ 
    private Brush _line1Brush = Brushes.Yellow; 
    private Brush _line2Brush = Brushes.Black; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public Brush Line1Brush 
    { 
     get { return _line1Brush; } 
     set 
     { 
      if (_line1Brush != value) 
      { 
       _line1Brush = value; 
       NotifyPropertyChanged("Line1Brush"); 
      } 
     } 
    } 
    public Brush Line2Brush 
    { 
     get { return _line2Brush; } 
     set 
     { 
      if (_line2Brush != value) 
      { 
       _line2Brush = value; 
       NotifyPropertyChanged("Line2Brush"); 
      } 
     } 
    } 

    private void NotifyPropertyChanged(string propertyName) 
    { 
     var del = PropertyChanged; 
     if (del != null) 
     { 
      del(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Eppure io ottenere i dati di legame errori che indica che WPF è alla ricerca di Line1Brush sul livello superiore MainWindow oggetto invece che su mio oggetto PulseImageViewModel. Qualche idea su cosa sto facendo male o se c'è un modo migliore per realizzare il mio obiettivo di colori dinamicamente modificabili sulla grafica vettoriale? Inoltre, sarebbe bello se la grafica fosse predefinita per un bel set di colori statici se l'utente non collegasse l'oggetto del modello di vista.

risposta

5

Il StaticResource avrà il DataContext dal Window credo. Questo cambia se usi DynamicResource?

Modifica Ottengo gli stessi risultati e Snoop non è utile. Anche lo spostamento di DataContext in XAML non modifica nulla. Per divertimento sono passato a trascinare un TextBox in un contenuto di Label, ed ecco che funziona ... Non ho idea di quale sia la differenza.

<Window.Resources> 
    <TextBlock x:Key="Text1" 
       Text="{Binding Line1Brush}" /> 
</Window.Resources> 
<Grid> 
    <!-- Confusingly enough, this works --> 
    <Label Content="{StaticResource Text1}" 
      DataContext="{Binding PulseImage1}" /> 
</Grid> 

Edit 2 le seguenti opere:

<DataTemplate x:Key="Graphic1"> 
    <Image> 
     <Image.Source> 
      <DrawingImage> 
       <DrawingImage.Drawing> 
        <DrawingGroup> 
         <DrawingGroup.Children> 
          <GeometryDrawing Geometry="F1 M 8.4073,23.9233L"> 
           <GeometryDrawing.Pen> 
            <Pen LineJoin="Round" 
             Brush="{Binding Line1Brush, Mode=OneWay}" /> 
           </GeometryDrawing.Pen> 
          </GeometryDrawing> 
          <GeometryDrawing Geometry="F1 M 3.6875,2.56251L"> 
           <GeometryDrawing.Pen> 
            <Pen LineJoin="Round" 
             Brush="{Binding Line2Brush, Mode=OneWay}" /> 
           </GeometryDrawing.Pen> 
          </GeometryDrawing> 
         </DrawingGroup.Children> 
        </DrawingGroup> 
       </DrawingImage.Drawing> 
      </DrawingImage> 
     </Image.Source> 
    </Image> 
</DataTemplate> 

Con il codice XAML che sembra:

<ContentPresenter ContentTemplate="{StaticResource Graphic1}" 
        Content="{Binding PulseImage1}" 
        Grid.Column="0" /> 
<ContentPresenter ContentTemplate="{StaticResource Graphic1}" 
        Content="{Binding PulseImage2}" 
        Grid.Column="1" /> 
+0

No, cambiando a DynamicResource non ha aiutato. Viene ancora visualizzato lo stesso errore di associazione dati nella finestra di output: errore del percorso di BindingExpression: proprietà 'Line1Brush' non trovata su 'oggetto' '' MainWindow '(Name =' ')'. –

+0

Hmm, mi chiedo perché questo richiede un DataTemplate/ContentPresenter per funzionare? Immagino che ciò funzionerebbe per qualsiasi luogo che richiedesse un'immagine, ad es. pulsante, voce di menu, ecc.? –

+0

Sì, questo funzionerebbe per ognuno di essi. Per qualsiasi motivo le associazioni vengono valutate con entusiasmo nella risorsa diretta 'DrawingImage'. Ma in un 'DataTemplate' sono valutati in uso. – user7116

Problemi correlati