Changing DrawingImage brush binded to DynamicResource - wpf

I have a DrawingImage object as a resource which uses brush color from DynamicResource like this:
<DrawingImage x:Key="img_building">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V512 H512 V0 H0 Z">
<DrawingGroup Opacity="1">
<GeometryDrawing Geometry="F1 M512,512z M0,0z M256.5,17.2L512,119.4 512,153.8 477.6,153.8C477.6,158.4 475.7,162.2 472,165.9 468.3,169.6 463.6,170.5 459,170.5L53,170.5C48.4,170.5 43.7,168.6 40,165.9 36.3,163.1 34.4,158.5 34.4,153.8L0,153.8 0,119.4 256.5,17.2z M68.8,188.2L136.6,188.2 136.6,392.6 171,392.6 171,188.2 238.8,188.2 238.8,392.6 273.2,392.6 273.2,188.2 341,188.2 341,392.6 375.4,392.6 375.4,188.2 443.2,188.2 443.2,392.6 459,392.6C463.6,392.6 468.3,394.5 472,397.2 475.7,400 477.6,404.6 477.6,409.3L477.6,426 35.3,426 35.3,409.3C35.3,404.7 37.2,400.9 40.9,397.2 44.6,393.5 49.3,392.6 53.9,392.6L69.7,392.6 69.7,188.2 68.8,188.2z M493.4,443.7C498,443.7 502.7,445.6 506.4,448.3 510.1,452 512,455.7 512,460.4L512,494.8 0.9,494.8 0.9,460.4C0.9,455.8 2.8,452 6.5,448.3 10.2,444.6 14.9,443.7 19.5,443.7L493.4,443.7z" >
<GeometryDrawing.Brush>
<SolidColorBrush Color="{DynamicResource Image.FillColor}" />
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingGroup>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
And then I'm using this resource in a template like this:
<DataTemplate x:Key="buildingImage">
<WrapPanel>
<WrapPanel.Resources>
<Style TargetType="{x:Type Image}">
<Setter Property="Margin" Value="0,0,4,0"></Setter>
<Setter Property="MaxHeight" Value="20"></Setter>
</Style>
</WrapPanel.Resources>
<Image Source="{DynamicResource img_building}" />
</WrapPanel>
</DataTemplate>
It's running fine but when I change the theme of my app, image remains same although the Image.FillColor changes.
I guess it's rendering the image for once and then uses the same rendered resource over and over again.
How to fix this? Is there a way to force a hard reload on DrawingImage in code behind?

Related

How to set size of Image.Source which is a static resource in XAML?

I have the following Image in my GUI:
<Image Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="2" Margin="5" Source="{Binding SelectedExternalCameraDevice.LiveStreamSource, FallbackValue={StaticResource LivestreamDefaultImage}, TargetNullValue={StaticResource LivestreamDefaultImage}}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stretch="Uniform"/>
The static resource for the fallback and targetnullvalue look as follows (This is basically taken from Windows's Image library - it is the icon "PlayVideo"):
<DrawingImage x:Key="LivestreamDefaultImage" >
<DrawingImage.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="{ui:DynamicColor SystemControlPageTextBaseMediumBrush}" Geometry="F1M16,16L0,16 0,0 16,0z" />
<GeometryDrawing Brush="{ui:DynamicColor SystemControlPageBackgroundChromeLowBrush}" Geometry="F1M16,4L16,12C16,13.103,15.103,14,14,14L2,14C0.897,14,0,13.103,0,12L0,4C0,2.897,0.897,2,2,2L14,2C15.103,2,16,2.897,16,4" />
<GeometryDrawing Brush="{ui:DynamicColor SystemControlPageTextBaseMediumBrush}" Geometry="F1M6,11L6,5 10.954,8z M14,3L2,3C1.448,3,1,3.448,1,4L1,12C1,12.552,1.448,13,2,13L14,13C14.552,13,15,12.552,15,12L15,4C15,3.448,14.552,3,14,3" />
<GeometryDrawing Brush="{ui:DynamicColor SystemControlPageBackgroundChromeLowBrush}" Geometry="F1M6,5L10.954,8 6,11z" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
As soon as the bound ImageSource in the ViewModel has a proper image, the Image control will stretch uniformly to the available space, keeping it's aspect ration. However, while the source is null the image takes the static resource as source, I have some default aspect ratio (which looks like 1:1). How can I set the width/height/aspect ration of the LivestreamDefaultImage, so that it will also stretch to the available space with my chosen dimensions?
If I understand you correctly, then try this Style:
<Image x:Name="image" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"
Grid.RowSpan="2" Margin="5"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{Binding SelectedExternalCameraDevice.LiveStreamSource}"/>
<Setter Property="Stretch" Value="Uniform"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedExternalCameraDevice.LiveStreamSource}" Value="{x:Null}">
<Setter Property="Source" Value="{DynamicResource LivestreamDefaultImage}"/>
<Setter Property="Stretch" Value="Fill"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>

Change Background color to a Visual pattern based

I have a list of elements (simple buttons with plain textblock) which are color coded based on the list item content. User can update the Listitem and thus listitem color should change. For certain listitem background colors like "Red", I want to add a pattern as well.
I have added the following VisualPatterns in XAML:
<Window.Resources>
<VisualBrush x:Key="FwdPattern" TileMode="Tile" Viewport="0,0,15,15" ViewportUnits="Absolute" Viewbox="0,0,15,15" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Grid>
<Path Data="M 0 15 L 15 0" Stroke="Gray" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
<VisualBrush x:Key="BckPattern" TileMode="Tile" Viewport="0,0,15,15" ViewportUnits="Absolute" Viewbox="0,0,15,15" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Grid>
<Path Data="M 0 0 L 15 15" Stroke="Gray" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
</Window.Resources>
Button template used in ListItem is:
<Border Background="{Binding BackgroundClr}">
<Button Name="MyButton" Content="Testing">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{Binding BackgroundClr}"/>
<Style.Triggers>
<!-- This does not work, see [http://stackoverflow.com/questions/39583263/brush-mvvm-binding-does-not-give-named-color/39583422#39583422][1] -->
<DataTrigger Binding="{Binding BackgroundClr}" Value="Red">
<Setter Property="Background" Value="{StaticResource BckPattern}"/>
</DataTrigger>
<!-- This does not work either, it goes in infinite loop
and StackOverflow exception is thrown-
probably because I am reading the background color in
the datatrigger and again updating it- but i dont know-->
<DataTrigger Binding="{Binding Background.Color, RelativeSource={RelativeSource Self}}" Value="Red">
<Setter Property="Background" Value="{StaticResource BckPattern}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Border>
Currently I have no other knowledge except the Button BackgroundClr from VM to determine if I need to provide a pattern or not.
Tried Solutions
One solution is to have a bound property- PatternName and based on it, determine which pattern to apply:
The above code works, but I have to have an additional property in VM
The other solution is to access VisualBrush in VM and directly apply the pattern in BackgroundClr - i have not figured out how to do this yet.
Which is a better solution or there any other way to achieve the same?
Thanks,
RDV
Change {Binding BackgroundClr} to {Binding BackgroundClr.Color}.

Bind to GeometryDrawing brush

I have 3 buttons in my user control, all 3 have little icons instead of text.
Image buttons
For example:
<controls:CheckButton Grid.Column="1" Style="{StaticResource ActionButtonStyle}">
<Image Source="{StaticResource Video}" Stretch="None"/>
</controls:CheckButton>
The image has this code to allow me to bind its color later:
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H25 V0 H0 Z">
<GeometryDrawing Brush="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=Control}}" Geometry="F0 M25,24z M0,0z M20.75,12C20.75,9.345,19.22,7.065,17,5.955L17,18.03C19.22,16.935,20.75,14.655,20.75,12L20.75,12z M0.5,7.5L0.5,16.5 6.5,16.5 14,24 14,0 6.5,7.5 0.5,7.5 0.5,7.5z" />
</DrawingGroup>
</DrawingImage.Drawing>
In order to set the color I use this style:
<Style x:Key="ActionButtonStyle" TargetType="ButtonBase">
<Setter Property="Foreground" Value="#FFE22880"/>
</Style>
I can see the pinkish color when in design time, but when running the app, this is what I get:
Black icons
*Some of the code is partial, but I've included everything important

Bounding box for button is effecting rotation animation

I have a button (25x25) with a background brush applied to it. If I rotate the button, WPF treats the button like a square rather than a circle. How do I get the button bounding box to be treated like the content, or background of the button?
Here's the markup for the background brush
<DrawingBrush x:Key="MetroArrowBrush"
Stretch="Uniform">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="#ffffff"
Geometry="F1M724.371,610.402C724.402,610.356 724.431,610.312 724.459,610.263 724.488,610.211 724.511,610.159 724.595,609.975 724.619,609.919 724.634,609.862 724.652,609.803 724.666,609.756 724.68,609.71 724.691,609.662 724.704,609.606 724.712,609.548 724.72,609.492 724.728,609.443 724.732,609.395 724.738,609.347 724.743,609.288 724.743,609.23 724.74,609.171 724.74,609.124 724.743,609.078 724.738,609.031 724.735,608.97 724.726,608.91 724.718,608.85 724.71,608.804 724.704,608.76 724.694,608.714 724.68,608.655 724.663,608.596 724.644,608.539 724.631,608.492 724.619,608.448 724.53,608.24 724.507,608.196 724.486,608.152 724.462,608.108 724.434,608.056 724.399,608.006 724.286,607.842 724.246,607.792 724.204,607.746 724.103,607.632L713.832,597.36C712.972,596.502 711.584,596.502 710.728,597.36 709.871,598.215 709.871,599.606 710.728,600.462L717.256,606.988 696.934,606.988C696.176,606.988 695.507,607.372 695.114,607.956 694.876,608.307 694.738,608.728 694.738,609.184 694.738,609.79 694.983,610.338 695.382,610.735 695.778,611.134 696.327,611.378 696.934,611.378L717.256,611.378 710.728,617.904C709.871,618.762 709.871,620.151 710.728,621.007 711.158,621.436 711.718,621.652 712.28,621.652 712.843,621.652 713.402,621.438 713.832,621.01L724.166,610.666C724.204,610.622 724.246,610.576 724.283,610.528 724.314,610.487 724.343,610.444 724.371,610.402z" />
<GeometryDrawing Brush="#ffffff"
Geometry="F1M711.074,631.265C698.899,631.265 688.993,621.358 688.993,609.185 688.993,597.012 698.899,587.106 711.074,587.106 723.246,587.106 733.153,597.012 733.153,609.185 733.153,621.358 723.246,631.265 711.074,631.265z M711.072,583.325C696.79,583.325 685.213,594.901 685.213,609.184 685.213,623.465 696.79,635.044 711.072,635.044 725.353,635.044 736.932,623.465 736.932,609.184 736.932,594.901 725.353,583.325 711.072,583.325z" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
And here's my button markup
<ToggleButton Name="btnToggleTaskBar"
Style="{StaticResource MetroArrow1RightStyle}"
FocusVisualStyle="{x:Null}"
VerticalAlignment="Top">
</ToggleButton>
<Style x:Key="MetroArrow1RightStyle"
TargetType="{x:Type Control}">
<Setter Property="Background"
Value="{DynamicResource MetroArrowBrush}" />
<Setter Property="BorderBrush"
Value="{x:Null}" />
<Setter Property="Foreground"
Value="{x:Null}" />
<Setter Property="BorderThickness"
Value="0" />
</Style>
I'm not sure what the problem is, but should you be animating RenderTransform instead of LayoutTransform?

Binding an ImageSource to a DrawingImage

<Style
TargetType="{x:Type local:ObjectWindow}"
BasedOn="{StaticResource {x:Type Window}}">
<Setter
Property="Icon">
<Setter.Value>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup>
<ImageDrawing
Rect="0,0,32,32"
ImageSource="{Binding View.ImageSource, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ObjectWindow}}}" />
<ImageDrawing
Rect="16,16,16,16"
ImageSource="{DynamicResource View_Image}" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Setter.Value>
</Setter>
</Style>
You can see what I'm trying to do. Trying to overlay two images on top of each other for a Window's Icon. One image is a dynamic resource, which works fine, the other is the result of a Binding expression against a property of the Window.
This however does not work. ImageDrawing doesn't seem to support bindings. Is there something I should be using other than ImageDrawing to accomplish this?

Resources