How to use DrawingBrush as Window.Icon? - c#

I have a DLL that has a ResourceDictionary containing a XAML image:
<DrawingBrush x:Key="imgFoo" ViewboxUnits="Absolute" Viewbox="0,0,128,128">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="#FF111111">
<GeometryDrawing.Pen>
<Pen LineJoin="Miter" StartLineCap="Square" EndLineCap="Square"/>
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<PathGeometry Figures="M 56.5625 ... 64.03125 45.46875 z"
FillRule="NonZero"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
Is it possible to use this DrawingBrush as Window.Icon?
using StaticResource or DynamicResource doesn't work:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Icon="{DynamicResource imgFoo}">
The only thing I found is using Window.Resources like this:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Icon="{DynamicResource imgFoo}">
<Window.Resources>
<DrawingImage x:Key="imgFoo">
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF111111">
<GeometryDrawing.Pen>
<Pen LineJoin="Miter" StartLineCap="Square"
EndLineCap="Square"/>
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<PathGeometry Figures="M 56.5625 ... 64.03125 45.46875 z"
FillRule="NonZero"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Window.Resources>
But this uses only a part of the DrawingBrush from the DLL file and creates duplicate XAML code.
Any suggestions on how I could use that DrawingBrush directly?

You could split the resource declaration into two parts and declare the GeometryDrawing and the DrawingBrush separately:
<GeometryDrawing x:Key="imgFooDrawing" Brush="#FF111111">
<GeometryDrawing.Pen>
<Pen LineJoin="Miter" StartLineCap="Square" EndLineCap="Square"/>
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<PathGeometry Figures="M10,64 L64,10 118,64 64,118Z" FillRule="NonZero"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
<DrawingBrush x:Key="imgFoo" ViewboxUnits="Absolute" Viewbox="0,0,128,128"
Drawing="{StaticResource imgFooDrawing}">
</DrawingBrush>
Now you could directly reuse the GeometryDrawing in a DrawingImage that is used as the Window's Icon:
<Window.Icon>
<DrawingImage Drawing="{DynamicResource imgFooDrawing}"/>
</Window.Icon>
In case you can't change the Resource DLL, you could bind the DrawingImage's Drawing property to the Drawing property of the DrawingBrush.
This would however require an ugly workaround because you can't use a DynamicResource as binding source. You may set the Tag property of the Window to the DrawingBrush, and then create a RelativeSource/FindAncestor binding:
<Window ... Tag="{DynamicResource imgFoo}">
<Window.Icon>
<DrawingImage Drawing="{Binding Tag.Drawing,
RelativeSource={RelativeSource AncestorType=Window}}"/>
</Window.Icon>
</Window>

Related

How to reuse a static GeometryDrawing in a DrawingImage using xaml

If I define in app.xaml a GeometryDrawing like this:
<GeometryDrawing x:Key="ReuseThis"
Pen="..."
Brush="..."
Geometry="..."/>
How can I then use it later in a DrawingImage like this:
<DrawingImage x:Key="FullImage">
<DrawingImage.Drawing>
<DrawingGroup>
<GeometryDrawing reuse it here somehow"{StaticResource ReuseThis}"/>
<Geometrydrawing ...>
<Geometrydrawing ...>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
I'm trying to avoid copying and pasting that GeometryDrawing in a bunch of DrawingImages I have.
Thanks
You can use the StaticResource Markup Extension in XAML Object Element Syntax:
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup>
<StaticResource ResourceKey="ReuseThis"/>
<GeometryDrawing .../>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>

Using Vector images as an image source. WPF , C#

i'm working on a project including loads of images. the thing is, like the title says, i have to convert all my vector images to png before i can use them as a image source.
I have vector images created in illustrator. I have them in the .ai project file , how do i go from here ?
My goal is to be able to do this :
<Image Width="70" Height="70" Source="MyVectorImage"/>
If you want to get the ImageSource from a geometry path image into your cs file, you can put the drawingImage into a resource file: Icons.xaml:
<DrawingImage x:Key="hazelnut">
<DrawingImage.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="Black">
<GeometryDrawing.Geometry>
<GeometryGroup>
<PathGeometry Figures="M 16.6309,18.6563C 17.1309,8.15625 29.8809,14.1563 29.8809,14.1563C 30.8809,11.1563 34.1308,11.4063 34.1308,11.4063C 33.5,12 34.6309,13.1563 34.6309,13.1563C 32.1309,13.1562 31.1309,14.9062 31.1309,14.9062C 41.1309,23.9062 32.6309,27.9063 32.6309,27.9062C 24.6309,24.9063 21.1309,22.1562 16.6309,18.6563 Z M 16.6309,19.9063C 21.6309,24.1563 25.1309,26.1562 31.6309,28.6562C 31.6309,28.6562 26.3809,39.1562 18.3809,36.1563C 18.3809,36.1563 18,38 16.3809,36.9063C 15,36 16.3809,34.9063 16.3809,34.9063C 16.3809,34.9063 10.1309,30.9062 16.6309,19.9063 Z ">
<PathGeometry.Transform>
<TransformGroup>
<ScaleTransform
CenterX="23"
CenterY="20"
ScaleX="0.45"
ScaleY="0.45" />
</TransformGroup>
</PathGeometry.Transform>
</PathGeometry>
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
And add in you App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Resources/Icons.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
And use it in your cs file like:
ImageSource image = ResourcePathToImageSource("hazelnut");
private ImageSource ResourcePathToImageSource(string resourcesName)
{
return (DrawingImage)Application.Current.TryFindResource(resourcesName);
}
You can use a DrawingImage as the Image's Source. DrawingImage uses a Geometry (i.e. vector graphics) instead of a bitmap.
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing>
<GeometryDrawing.Pen>
<Pen Thickness="2" Brush="Black"/>
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="100,100,100,100"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
You can of course also bind the Source property to a view model property of type ImageSource, which contains a DrawingImage that you would create from your original vector data.

How to handle events in Custom Controls

I am trying to create a simple controller, here is my Generic.xaml;
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TopluNotEkle">
<Style TargetType="{x:Type local:FileSelector}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FileSelector}">
<Button BorderThickness="8,8,8,8" Background="Gray" x:Name="MainButton">
<Button.BorderBrush>
<DrawingBrush TileMode="Tile" Viewport="0,0,64,64" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="LightGray">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,100,100" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="DarkGray">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50"/>
<RectangleGeometry Rect="50,50,50,50"/>
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Button.BorderBrush>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="BlueViolet" FontWeight="Bold" FontSize="20">Drag & Drop</TextBlock>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
and this is my code behind
public class FileSelector : Control
{
static FileSelector()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FileSelector), new FrameworkPropertyMetadata(typeof(FileSelector)));
MainButton.Drop += myDrop;
}
static void myDrop(object sender, DragEventArgs e)
{
Debug.Fail("This is called");
}
}
I am getting The name MainButton does not exist in current context error. I also tried setting Drop = "myDrop", however, that also didn't work.
How can I listen to events on my component?
Buttons have been assigned a name by the x:Name attribute for us to be able to find them in code and hook up their click event handlers. This is done by overriding the OnApplyTemplate in our Custom Control class.
Retrieve the Button from the template
public override void OnApplyTemplate()
{
Button mainButton = GetTemplateChild("MainButton") as Button;
if (mainButton != null)
mainButton.Click += MainBtnClick;
}
Follow a complete tutorial like for example (but not necessarily) this: http://blog.magnusmontin.net/2013/03/16/how-to-create-a-custom-window-in-wpf/
So your problem is not what you are setting as a 'Drop' value, it is the reference to the MainButton that is not available.
I think you are trying to create a custom control, which typically defined as UserControl, not as a part of ResourceDictionary. I might be wrong as I haven't worked with WPF for several years. Here is how to create user control:
<UserControl x:class= "YourNamespace.FileSelector" ... other xmlns garbage>
<Button BorderThickness="8,8,8,8" Background="Gray" x:Name="MainButton">
<Button.BorderBrush>
<DrawingBrush TileMode="Tile" Viewport="0,0,64,64" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="LightGray">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,100,100" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="DarkGray">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50"/>
<RectangleGeometry Rect="50,50,50,50"/>
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Button.BorderBrush>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="BlueViolet" FontWeight="Bold" FontSize="20">Drag & Drop</TextBlock>
</Button>
Also check out this tutorial: https://www.tutorialspoint.com/wpf/wpf_custom_controls.htm

Set InkCanvas Background DrawingBrush via C#

I want to set the following XAML attributes via C#:
<InkCanvas.Background>
<DrawingBrush Stretch="None" TileMode="Tile" Viewport="0,0,2,2" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,2,2" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="#FFE3E3E3">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,1,1" />
<RectangleGeometry Rect="1,1,1,1" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</InkCanvas.Background>
How should I go about this?
I have found the solution myself and leave it here for anyone else, facing the same issue.
http://www.c-sharpcorner.com/uploadfile/mahesh/wpf-drawing-brush/ pretty much is what i was looking for.

How to specify the default value if the binding fails?

I have a DrawingBrush as follow :-
<DrawingBrush x:Key="MY_ICON" Viewbox="0,0,39.125,39.125" ViewboxUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=uiEntityViews:BaseView}, Path=Color}" Geometry="F1M19.5625,0.999954C29.8144,0.999954 38.125,9.31053 38.125,19.5625 38.125,29.8142 29.8143,38.1249 19.5625,38.1249 9.31073,38.1249 1,29.8142 1,19.5625 1,9.31053 9.31064,0.999954 19.5625,0.999954z">
<GeometryDrawing.Pen>
<Pen DashCap="Square" EndLineCap="Flat" LineJoin="Round" MiterLimit="10" StartLineCap="Flat" Thickness="2">
<Pen.Brush>
<LinearGradientBrush EndPoint="0.849422,0.849423" StartPoint="0.150577,0.150578">
<GradientStop Color="#FF657783" Offset="0"/>
<GradientStop Color="White" Offset="0.146"/>
<GradientStop Color="#FF2C4758" Offset="1"/>
</LinearGradientBrush>
</Pen.Brush>
<Pen.DashStyle>
<DashStyle/>
</Pen.DashStyle>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
I used the above brush inside the style as the following:-
<Style x:Key="NODE_ICON" TargetType="Rectangle">
<Setter Property="Fill">
<Setter.Value>
<DrawingBrush TileMode="None">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{StaticResource MY_ICON}">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<DrawingGroup>
<DrawingGroup.Transform>
<TranslateTransform X="0.2" Y="0.2" />
</DrawingGroup.Transform>
<GeometryDrawing Brush="{StaticResource NODE_ICON}">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Setter.Value>
</Setter>
Right now, I am getting this error - System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Views.UIEntityViews.BaseView', AncestorLevel='1''. BindingExpression:Path=Color; DataItem=null; target element is 'GeometryDrawing' (HashCode=3377278); target property is 'Brush' (type 'Brush').
It seems that the binding is not working. Is there a way to specify the default value for color, lets say <GeometryDrawing Brush="{StaticResource ROADM_ICON, color=Gray}"> if the binding fails?
Use FallbackValue.....<GeometryDrawing Brush="{StaticResource NODE_ICON, FallbackValue=Gray}">
As #Carmine suggested using FallbackValue, I was able to make it work making following changes:-
<GeometryDrawing Brush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=uiEntityViews:CanvasLinkConnectionPointBaseView}, Path=MeSiteColor, FallbackValue=Gray}" Geometry="F1M19.5625,0.999954C29.8144,0.999954 38.125,9.31053 38.125,19.5625 38.125,29.8142 29.8143,38.1249 19.5625,38.1249 9.31073,38.1249 1,29.8142 1,19.5625 1,9.31053 9.31064,0.999954 19.5625,0.999954z">

Categories