如何使WPF DrawingImage的元素颜色动态化?

Kei*_*ill 7 wpf binding

我们需要使某些矢量图形图像在运行时改变图形中某些元素的颜色.似乎根据静态或动态资源值设置这些颜色是行不通的.我们希望拥有相同图形的多个版本,每个版本都具有将某些图形元素(路径,线等)设置为不同颜色的能力,因此我认为动态资源方法不起作用.这留下了数据绑定,这似乎是正确的方法.我们更新图形以使用数据绑定expr而不是硬编码的画笔颜色,如下所示:

<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>
Run Code Online (Sandbox Code Playgroud)

然后我们在这种情况下为Graphic1的每个实例创建一个视图模型对象(支持INotifyPropertyChanged)实例,并确保它同时具有a Line1BrushLine2Brush属性.听起来不错,但我无法让它发挥作用.我假设这个图形,它本身是在Image对象的资源字典中定义的,我尝试DataContext在Debug窗口中设置它们和我得到的数据绑定错误输出.这是Image XAML:

<Image x:Name="Pulse1" Grid.Column="0" Source="{StaticResource Graphic1}"/>
<Image x:Name="Pulse2" Grid.Column="1" Source="{StaticResource Graphic1}"/>
Run Code Online (Sandbox Code Playgroud)

然后在Window的Initialize方法中我设置他们的数据上下文,如下所示:

 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;
}
Run Code Online (Sandbox Code Playgroud)

其中PulseImageViewModel(如下所示)定义了两个属性Line1BrushLine2Brush,其中每个触发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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,我得到数据绑定错误,表明WPF正在寻找Line1Brush顶级MainWindow对象而不是我的PulseImageViewModel对象.对于我做错了什么或是否有更好的方法来实现我在矢量图形上动态可变颜色的目标的任何想法?此外,如果用户没有连接视图模型对象,那么如果图形可以默认为漂亮的静态颜色集,那将是很好的.

use*_*116 5

StaticResource是要具有DataContextWindow我相信.如果使用,这会改变DynamicResource吗?

编辑我得到的结果与你相同,而Snoop没有帮助.即使将DataContext移动到XAML也不会改变任何内容.为了好玩,我转而将TextBox拉成Label的内容,并且看起来有用......不知道有什么区别.

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

编辑2以下工作:

<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>
Run Code Online (Sandbox Code Playgroud)

随着XAML看起来像:

<ContentPresenter ContentTemplate="{StaticResource Graphic1}"
                  Content="{Binding PulseImage1}"
                  Grid.Column="0" />
<ContentPresenter ContentTemplate="{StaticResource Graphic1}"
                  Content="{Binding PulseImage2}"
                  Grid.Column="1" />
Run Code Online (Sandbox Code Playgroud)