2011-02-09 11 views
7

Tenemos la necesidad de hacer que ciertas imágenes gráficas vectoriales cambien el color de ciertos elementos dentro del gráfico en tiempo de ejecución. Parecería que no funcionaría establecer esos colores basados ​​en valores de recursos estáticos o dinámicos. Queremos tener múltiples versiones del mismo gráfico, cada una con la capacidad de establecer ciertos elementos gráficos (ruta, línea, etc.) a diferentes colores, por lo que no creo que un enfoque de recurso dinámico funcione. Eso deja el enlace de datos que parece ser el enfoque correcto. Actualizamos el gráfico para utilizar una expr enlace de datos en lugar de un pincel de color codificado de este modo:¿Cómo se puede hacer que el color de los elementos de un WPF DrawingImage sea dinámico?

<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> 

entonces se crea un objeto de vista del modelo de instancia (apoyo INotifyPropertyChanged) para cada instancia de Graphic1 en este caso y hacemos seguro que tiene una propiedad Line1Brush y otra Line2Brush. Suena bien, pero no puedo hacer que funcione. Supongo que este gráfico, que a su vez está definido en un diccionario de recursos para los objetos de imagen, intento establecer su DataContext y obtengo el resultado de error de enlace de datos en mi ventana de depuración. Aquí está el XAML Image:

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

Y luego, en el método de la ventana Initialize que establece el contexto de datos de este 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; 
} 

Dónde PulseImageViewModel (mostrada a continuación) define dos propiedades Line1Brush y Line2Brush, cada uno de los cuales disparar el 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)); 
     } 
    } 
} 

Sin embargo, puedo recuperar los datos de unión errores que indica que WPF está buscando Line1Brush en el nivel superior MainWindow objeto en lugar de en mi objeto PulseImageViewModel. ¿Alguna idea sobre lo que estoy haciendo mal o si hay una mejor manera de lograr mi objetivo de colores dinámicamente cambiables en los gráficos vectoriales? Además, sería bueno si los gráficos pudieran establecer de manera predeterminada un conjunto de colores agradable y estático si el usuario no conectara el objeto del modelo de visualización.

Respuesta

5

El StaticResource va a tener el DataContext del Window creo. ¿Esto cambia si usa DynamicResource?

Editar me da los mismos resultados que usted, y Snoop no está siendo útil. Incluso mover el DataContext al XAML no cambia nada. Para divertirme cambié a tirar de un TextBox en el contenido de una etiqueta, y he aquí que funciona ... No tengo idea de cuál es la diferencia.

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

Editar 2 las siguientes obras:

<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 el XAML que parece:

<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 no ayudaron. Todavía obtiene el mismo error de enlace de datos en la ventana de salida - Error de ruta de BindingExpression: la propiedad 'Line1Brush' no se encuentra en 'object' '' 'MainWindow' (Name = '') '. –

+0

Hmm, me pregunto por qué esto requiere un DataTemplate/ContentPresenter para funcionar? Supongo que esto funcionaría para cualquier lugar que requiera una imagen, p. botón, elemento de menú, etc. –

+0

Sí, esto funcionaría para cualquiera de ellos. Por alguna razón, los enlaces se evalúan ansiosamente en el recurso directo 'DrawingImage'. Pero en un 'DataTemplate' se evalúan en el momento del uso. – user7116

Cuestiones relacionadas