For some reason, my ImageBrush background as an odd blurry drop shadow to it.
<Button Style="{StaticResource SeamlessBtn}" Width="30" Height="30" Click="ToggleTheme"
BorderBrush="Transparent" Margin="10,10,105,408" Foreground="Transparent">
<Button.Background>
<ImageBrush x:Name="BrightSwitch" ImageSource="/Images/BootstrapIcons-MoonFill.png"/>
</Button.Background>
</Button>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="Button"
x:Key="SeamlessBtn">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="BorderBrush" Value="Transparent"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Edit: I am using materialDesignTheme
Since the geometry is readily available.
https://icons.getbootstrap.com/icons/moon-fill/
I would suggest trying that.
I put such geometries in a resource dictionary I merge in app.xaml but that could be anywhere in scope of your button instead:
<Window.Resources>
<Geometry x:Key="MoonGeometry">
M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z
</Geometry>
</Window.Resources>
Since that's seems to be the only thing you have in your button you can just make it content. In just a plain button:
<Button>
<Path Data="{StaticResource MoonGeometry}"
Fill="Black"
Stretch="Uniform"/>
</Button>
Or if you particularly wanted a background and brush:
<Button>
<Button.Background>
<DrawingBrush Stretch="Uniform">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="Black"
Geometry="{StaticResource MoonGeometry}"/>
</DrawingBrush.Drawing>
</DrawingBrush>
</Button.Background>
</Button>
Either approach gives you a sharp picture because it's using vectors.
I have got button Lock and button Unlock placed together in my app. The problem is that they have vector SVG images as content, both are black, so it seems that both buttons are enabled, so I need to change the color on gray, if it's unabled.
Assigning image as button content is realized like this:
<Button x:Name="LockButton" Content="{StaticResource LockButton}"/>
So lock image is some style:
<Rectangle x:Key="LockButton" Style="{StaticResource ButtonRectangle}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill">
<VisualBrush.Visual>
<Canvas Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="34.8333" Height="41.1667" Canvas.Left="20.5833" Canvas.Top="17.4167" Stretch="Fill" Fill="#FF000000" Data="M 12 0 C 8.699219 0 6 2.699219 6 6 L 6 11 L 3 11 L 3 24 L 21 24 L 21 11 L 18 11 L 18 6 C 18 2.699219 15.300781 0 12 0 Z M 12 2 C 14.21875 2 16 3.78125 16 6 L 16 11 L 8 11 L 8 6 C 8 3.78125 9.78125 2 12 2 Z"/>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.OpacityMask>
</Rectangle>
And for this Rectangle there is another style:
<Style x:Key="ButtonRectangle" TargetType="Rectangle">
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
<Setter Property="Fill" Value="Black" />
</Style>
So I think, that I need to make DataTrigger for some of these blocks. But I don't know how to bind IsEnabled property of button in inner styles. Another idea is to make the same rectangle style with gray fill and make DataTrigger, which will apply different styles to button, depending on value of IsEnabled property.
So, what do you think, how would you solve this?
Better use the Path as Content of a Button and bind its Fill property to the Button's Foreground.
<Geometry x:Key="LockGeometry">M 12 0 C 8.699219 0 6 2.699219 6 6 L 6 11 L 3 11 L 3 24 L 21 24 L 21 11 L 18 11 L 18 6 C 18 2.699219 15.300781 0 12 0 Z M 12 2 C 14.21875 2 16 3.78125 16 6 L 16 11 L 8 11 L 8 6 C 8 3.78125 9.78125 2 12 2 Z</Geometry>
...
<Button Style="{StaticResource IconButtonStyle}">
<Path Data="{StaticResource LockGeometry}"
Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType=Button}}"
Width="16" Height="16" Margin="4" Stretch="Fill"/>
</Button>
The Foreground would be set by a Style like:
<Style x:Key="IconButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
don't put visual elements (Rectangle) in Resources - it makes difficult to modify and use them. instead define VisualBrush as resource, apply OpacityMask in Rectangle Style, add DataTrigger in RectangleStyle, and then use rectangle with that Style as Button.Content:
<VisualBrush Stretch="Fill" x:Key="LockButtonIco">
<VisualBrush.Visual>
<Canvas Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="34.8333" Height="41.1667" Canvas.Left="20.5833" Canvas.Top="17.4167" Stretch="Fill" Fill="#FF000000" Data="M 12 0 C 8.699219 0 6 2.699219 6 6 L 6 11 L 3 11 L 3 24 L 21 24 L 21 11 L 18 11 L 18 6 C 18 2.699219 15.300781 0 12 0 Z M 12 2 C 14.21875 2 16 3.78125 16 6 L 16 11 L 8 11 L 8 6 C 8 3.78125 9.78125 2 12 2 Z"/>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
<Style x:Key="ButtonRectangle" TargetType="Rectangle">
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
<Setter Property="OpacityMask" Value="{StaticResource LockButtonIco}" />
<Setter Property="Fill" Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource AncestorType=Button}}" Value="False">
<Setter Property="Fill" Value="Blue" />
</DataTrigger>
<Style.Triggers>
</Style>
<Button x:Name="LockButton">
<Rectangle Style="{StaticResource ButtonRectangle}"/>
</Button>
or maybe apply OpacityMask to each Rectangle, not in style:
<Button x:Name="LockButton">
<Rectangle Style="{StaticResource ButtonRectangle}"
OpacityMask="{StaticResource LockButtonIco}"/>
</Button>
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}.
I am pretty new with WPF design (and design in general), and I need help with one task.
I have a style for a button that contains some data in a Path, which draws an icon on it (basically simple add new icon). Now I would like to make a copy icon out of it.
I could not find a way to manipulate with Path I have in Blend, so what I had in mind was:
1) Copy Path data so we can draw two icons (to have two Path objects in Content)
2) Shift first a little to the left and top
3) Shift second a little to the right and bottom
4) Make second one overlap first one
This is what I did:
Since we cannot have two elements set for Content, I have added one Grid element, and inside I copied Path element twice. Then I repositioned both path to simulate duplicate data.
<Setter Property="Content">
<Setter.Value>
<Grid>
<Path Data="..." Margin="10" Stretch="Fill" Fill="{StaticResource IconBrush}" RenderTransformOrigin="0.5,0.4">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="-90" />
<TranslateTransform />
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path Data="..." Margin="10" Stretch="Fill" Fill="{StaticResource IconBrush}" RenderTransformOrigin="0.5,0.6">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="-90" />
<TranslateTransform />
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>
</Setter.Value>
</Setter>
Problem: I do not get overlap with second icon (basically everything is transparent. That means that I probsably need to delete some points on first icon, but I could not achieve that in Blend?
Can anyone share some light how to achieve what I need?
Not sure what your icons should look like, but the following XAML will display two overlapping plus signs using the same Path data for both, but with a simple TranslateTransform to offset the second one.
<Grid>
<Path Fill="#FF008000" >
<Path.Data>
<PathGeometry Figures="m 30 25.362188 0 30.000001 -30 0 0 20 30 0 0 29.999991 20 0 0 -29.999991 30 0 0 -20 -30 0 0 -30.000001 -20 0 z" FillRule="nonzero"/>
</Path.Data>
</Path>
<Path Fill="#FF92D050" >
<Path.Data>
<PathGeometry Figures="m 30 25.362188 0 30.000001 -30 0 0 20 30 0 0 29.999991 20 0 0 -29.999991 30 0 0 -20 -30 0 0 -30.000001 -20 0 z" FillRule="nonzero"/>
</Path.Data>
<Path.RenderTransform>
<TranslateTransform X="25" Y="-25"/>
</Path.RenderTransform>
</Path>
</Grid>
I would recommend not putting margins or 'Stretch' properties in your actual path objects. Take care of that in the Grid container they are in, or a containing Viewbox if you need to scale them up or down.
EDIT
If you are actually using the Fill property of the Path object to draw the icon geometry, as with a VisualBrush object, instead of the Path.Data, then you don't want to use a Path in the first place. Just use two Rectangle objects, with your 'IconBrush' Fill in the grid and do the TranslateTransform on one of them so that they overlap to the desired amount. Remember that with XAML, the object that appears last in the listing is rendered on top.
EDIT 2
<Grid>
<Path Fill="#FFFFFFFF">
<Path.Data>
<PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path Fill="#FFB3B3B3">
<Path.Data>
<PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path Fill="#FFFFFFFF">
<Path.Data>
<PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
</Path.Data>
<Path.RenderTransform>
<TranslateTransform X="30" Y="30"/>
</Path.RenderTransform>
</Path>
<Path Fill="#FFB3B3B3">
<Path.Data>
<PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
</Path.Data>
<Path.RenderTransform>
<TranslateTransform X="30" Y="30"/>
</Path.RenderTransform>
</Path>
</Grid>
The above XAML is probably way too big for your needs. You can just put the whole grid in a Viewbox and then set the Height and Width properties of the Viewbox to get it to the size you need.
EDIT 3
Custom button style:
<Style x:Key="btnCustom" TargetType="{x:Type Button}">
<Setter Property="Content">
<Setter.Value>
<Viewbox>
<Grid Margin="0,0,30,30">
<Path Fill="#FFFFFFFF">
<Path.Data>
<PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path Fill="#FFB3B3B3">
<Path.Data>
<PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path Fill="#FFFFFFFF">
<Path.Data>
<PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
</Path.Data>
<Path.RenderTransform>
<TranslateTransform X="30" Y="30"/>
</Path.RenderTransform>
</Path>
<Path Fill="#FFB3B3B3">
<Path.Data>
<PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
</Path.Data>
<Path.RenderTransform>
<TranslateTransform X="30" Y="30"/>
</Path.RenderTransform>
</Path>
</Grid>
</Viewbox>
</Setter.Value>
</Setter>
</Style>
Button implementation:
<Button HorizontalAlignment="Right" Style="{StaticResource btnCustom}"
Height="30" Width="100"/>
What it looks like in the WPF Window:
I have a borderless and transparent window in WPF, with some fancy decoration at the bottom. There's a custom footer with some non conventional curves and what not showing the company logo. This window needs to be resizable with a grip in the bottom right corner like conventional windows.
Anyways, I have put my own ResizeGrip in a place that is actually on the footer, however the default grip still shows up and it's floating in space due to the invisible window.
How do I hide the default ResizeGrip?
The appearance of a resize grip is controlled via the ResizeMode dependency property on the Window.
If this is set to CanResizeWithGrip:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="50" Width="150"
WindowStyle="None" AllowsTransparency="True" Background="#19FFFFFF"
ResizeMode="CanResizeWithGrip">
<Grid></Grid>
</Window>
The Window will look like this:
If it is set to CanResize (the default):
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="50" Width="150"
WindowStyle="None" AllowsTransparency="True" Background="#19FFFFFF"
ResizeMode="CanResize">
<Grid></Grid>
</Window>
The Window will look as follows:
So to hide the default grip, I overwrote the default ResizeGrip style such that it's visibility is hidden. Easy with the help of Expression Blend 2.
<Style TargetType="{x:Type ResizeGrip}">
<Setter Property="MinWidth" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
<Setter Property="MinHeight" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ResizeGrip}">
<Grid SnapsToDevicePixels="True" Background="{TemplateBinding Background}">
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Visibility" Value="Hidden"/>
</Style>
Then I set up my own ResizeGrip on my custom window decoration with a style that is identical to the default grip style.
<SolidColorBrush x:Key="ResizeGripperForeground" Color="#B8B4A2"/>
<Style x:Key="VisibleResizeGrip" TargetType="{x:Type ResizeGrip}">
<Setter Property="MinWidth" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
<Setter Property="MinHeight" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ResizeGrip}">
<Grid SnapsToDevicePixels="True" Background="{TemplateBinding Background}">
<Path Fill="White" HorizontalAlignment="Right" Margin="0,0,2,2" VerticalAlignment="Bottom" Data="M 8,0 L 10,0 L 10,2 L 8,2 Z M 4,4 L 6,4 L 6,6 L 4,6 Z M 8,4 L 10,4 L 10,6 L 8,6 Z M 0,8 L 2,8 L 2,10 L 0,10 Z M 4,8 L 6,8 L 6,10 L 4,10 Z M 8,8 L 10,8 L 10,10 L 8,10 Z"/>
<Path Fill="{StaticResource ResizeGripperForeground}" HorizontalAlignment="Right" Margin="0,0,3,3" VerticalAlignment="Bottom" Data="M 8,0 L 10,0 L 10,2 L 8,2 Z M 4,4 L 6,4 L 6,6 L 4,6 Z M 8,4 L 10,4 L 10,6 L 8,6 Z M 0,8 L 2,8 L 2,10 L 0,10 Z M 4,8 L 6,8 L 6,10 L 4,10 Z M 8,8 L 10,8 L 10,10 L 8,10 Z"/>
<Path Data="M8,0L10,0 10,2 8,2z M4,4L6,4 6,6 4,6z M8,4L10,4 10,6 8,6z M0,8L2,8 2,10 0,10z M4,8L6,8 6,10 4,10z M8,8L10,8 10,10 8,10z" Fill="White" HorizontalAlignment="Right" Margin="0,0,2,2" VerticalAlignment="Bottom" />
<Path Data="M8,0L10,0 10,2 8,2z M4,4L6,4 6,6 4,6z M8,4L10,4 10,6 8,6z M0,8L2,8 2,10 0,10z M4,8L6,8 6,10 4,10z M8,8L10,8 10,10 8,10z" Fill="{StaticResource ResizeGripperForeground}" HorizontalAlignment="Right" Margin="0,0,3,3" VerticalAlignment="Bottom" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>