Create borderbrush "around the border path" - c#

I'm trying to create a border with a gradient stroke around the border path, not around the full element but around the border itself.
A simple example of what I do not want is:
<Border BorderThickness="10" Width="100" Height="50">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="Black" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
This creates a border that looks like:
What I to achieve wish is something like the image below. Notice that this achieved by blurring, I rather not do that as that would limit the what can be done - and more importantly: it would either blur all child elements, or I'd lose the ability to walk the visual tree with the border at the expected position. (Border would be a sibbling to its "content")

Dig a bit into shadow of border it looks closer
<Border BorderThickness="5" Width="100" Height="50" CornerRadius="5" BorderBrush="Gray">
<Border.Effect>
<DropShadowEffect BlurRadius="20" Opacity="1" ShadowDepth="1" Color="Black">
</DropShadowEffect>
</Border.Effect>
</Border>
It will give you something like
Alternatively
you can draw Blured dummy border on the same place with the current one (Bind width and height), but lower in the markup, in that case UI will draw dummy border over your container border and you'll see bluring without harming the tree
<Border BorderThickness="0" Width="100" Height="50" CornerRadius="5" BorderBrush="Gray" x:Name="x">
<TextBox Width="70" Height="20">Some data</TextBox>
</Border>
<Border BorderThickness="5" Width="{Binding Width, ElementName=x}" Height="{Binding Height, ElementName=x}" CornerRadius="0" BorderBrush="Black">
<Border.Effect>
<BlurEffect Radius="10"></BlurEffect>
</Border.Effect>
</Border>

If you really want to be able to have a blurred gradient border i think you might have to go with something like this.
Create a trapeze-shape with your gradient:
Then copy this shape 3 times and apply some render-transformations to get the border shape
Apply a Blur Effect on the whole shape
I made all those screenshots directly from the WPF result.

Related

Can't set keyboard focus to ScrollViewer in WPF

I have a control with a button and scrollviewer next to it. I want to be able to change keyboard focus via arrow keys or the tab key. I've set scrollviewer's focusable to true, but it seems it still cannot gain focus via keyboard. If I click on the scrollviewer then I can scroll using the arrow keys (up/down), but I cannot actually navigate to it without using the mouse.
I can focus on the button fine and if I change the scrollviewer for another control (in the same position) such as ScrollContentPresenter then the other control can switch focus between itself and the button as I would expect.
I am trying to understand why ScrollViewer cannot gain focus here. All search results I have found have the reverse problem (ScrollViewer stealing focus). Also if I set focusable to true on a control inside the ScrollViewer then it can gain focus as well. It just seems to be impossible for ScrollViewer to gain focus.
Here's the code sample with commented out ScrollContentPresenter (which can gain focus when used to replace ScrollViewer).
<Grid >
<StackPanel Orientation="Horizontal">
<Button Height="50" Width="300" Style="{StaticResource ButtonStyleLol}" />
<ScrollViewer Height="200" Width="1300" Focusable="True">
<StackPanel Height="1000" >
<StackPanel.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="#FFF71E1E" Offset="1"/>
</LinearGradientBrush>
</StackPanel.Background>
</StackPanel>
</ScrollViewer>
<!--<ScrollContentPresenter Height="200" Width="1300" Focusable="True">
<ScrollContentPresenter.Content>
<StackPanel Height="1000">
<StackPanel.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="#FFF71E1E" Offset="1"/>
</LinearGradientBrush>
</StackPanel.Background>
</StackPanel>
</ScrollContentPresenter.Content>
</ScrollContentPresenter>-->
</StackPanel>
</Grid>
Setting the IsTabStop property of the ScrollViewer to true seems to work for me:
<ScrollViewer IsTabStop="True" Focusable="True">

Height and Width with a menu

<Menu Height="50" Margin="0,0,0,0" HorizontalAlignment="Stretch" FlowDirection="RightToLeft">
<Menu.Background>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
<GradientStop Color="#FFB3DDF2" Offset="1.0"/>
<GradientStop Color="#FFD6E9F4" Offset="0.0"/>
</LinearGradientBrush>
</Menu.Background>
</Menu>
This Menu will stretch no matter how long the page is and doesn't need to have a width.
<Menu Width="350" Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Left" FlowDirection="RightToLeft" DockPanel.Dock="Bottom">
<Menu.Background>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
<GradientStop Color="#FFD6E9F4" Offset="1.0"/>
<GradientStop Color="White" Offset="0.0"/>
</LinearGradientBrush>
</Menu.Background>
</Menu>
I want to do the same with this menu however it requires a height which means if i stretch the page down, the menu size will not stretch with the page. When I don't put a height into the code no menu bar appears. My question is how come I don't need a width for the menu bar but i need a height.
Thanks in advance
It is by design.
A menu bar is something that is assumed to stretch across the control it is contained in. That's why it doesn't need a width.
It needs a height because you can put any content inside it.
A stretch height wouldn't have a whole lot of meaning for a menu control, since it'd just be a large blank area of its background color, if WPF were to draw it for you.

xaml ScrollViewer, blurred border - Windows Store App

Is it somehow possible to have somekind of a blurred border when scrolling? For better understanding I added a picture of what I want to acchieve.
The restriction that I have is, that underneath the ScrollViewer I have got a background Image. Thus, I cant just use a filled Rectangle with white to transparent gradient at the left side of the ScrollViewer.
Since WinRT dropped support for OpacityMask and I'm not sure if you'd want to set it with an Alpha channel. With that said though, there's pretty much always a work around. So what if you just utilize the natural z-order instead and fake it? Something like this;
<!-- Grid as Container -->
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible">
<!-- example backgrounds, like images, just for the concept example. -->
<StackPanel Orientation="Horizontal">
<Rectangle Height="75" Width="300" Fill="Red" Margin="20,0"/>
<Rectangle Height="75" Width="300" Fill="Red" Margin="20,0"/>
<Rectangle Height="75" Width="300" Fill="Red" Margin="20,0"/>
<Rectangle Height="75" Width="300" Fill="Red" Margin="20,0"/>
<Rectangle Height="75" Width="300" Fill="Red" Margin="20,0"/>
</StackPanel>
</ScrollViewer>
<!-- An adhoc gradient overlay to just float over the ScrollViewer itself.
Then using Margin to fit it to the shape of the Scrollviewer and still
allow hit visibility to the scrollbar etc. -->
<Rectangle Width="50" HorizontalAlignment="Left" Margin="1,1,0,20">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0.1,0.5">
<GradientStop Color="White" Offset="0.3"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
Of course you'll probably want to tweak some values like the Rectangle Margin in the example to make it look exactly right with your own setup, but the concept should be there and is an option. Hope this helps.

Paint a control twice

I'm working on a very eye-candy program and I'm required to add a reflection and a 3D depth to the controls.
On both cases I need to paint the control a couple of times, but with changes:
For the reflection I'll have to repaint the control again at the bottom + flip it.
And as for the 3D depth, it's just a lot of copies behind + to the side.
The question is how can I get the image of the control in order to modify it and paint it below / behind it? Do you have any caveats and warnings / helpful tips regarding such actions? (I've never tried anything similar before).
Many thanks.
In WPF you can use a VisualBrush as the background/fill of another element (such as a Rectangle). This VisualBrush has a Visual property that can be bound to another control in order to mimic its content. Using transforms and alpha masks on this control can help apply reflection-style effects. For example:
<StackPanel Width="200">
<TextBox x:Name="tb">Hello world</TextBox>
<Rectangle Height="40" HorizontalAlignment="Stretch">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=tb}" />
</Rectangle.Fill>
<Rectangle.RenderTransform>
<ScaleTransform CenterY="20" ScaleY="-1" />
</Rectangle.RenderTransform>
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#00000000" Offset="0" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</StackPanel>

Creating a reflection of a WindowsFormHost in wpf

I am very new to WPF and I am a bit stuck.
I'm trying to create a demo program that displays several embedded win forms applications. I'd like to add a reflection of the form, but most of the existing tutorials I've seen seen for image reflections do not work.
If anyone can point me in the right direction I would really appreciate it.
Here is the relevent XAML - the form control is added to the embedForm stack panel dynamically.
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Name="inkBorder" Grid.Row="0" VerticalAlignment="Bottom" Margin="20"
Width="400" Height="500" CornerRadius="5" BorderThickness="4">
<Border.BorderBrush>
<LinearGradientBrush SpreadMethod="Reflect" StartPoint="0,0" EndPoint="0.5,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Gray" Offset="0" />
<GradientStop Color="#eeeeee" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<StackPanel Name="EmbedForm" Height="100" Width="400" ></StackPanel>
</Border>
<Rectangle Grid.Row="1" VerticalAlignment="Top"
Width="{Binding ElementName=inkBorder,Path=ActualWidth}"
Height="{Binding ElementName=inkBorder,Path=ActualHeight}">
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#66000000" />
<GradientStop Offset="1.0" Color="#00000000" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.OpacityMask>
<Rectangle.Fill>
<VisualBrush
Visual="{Binding ElementName=inkBorder}">
<VisualBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-1" />
<TranslateTransform Y="1" />
</TransformGroup>
</VisualBrush.RelativeTransform>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
To clarify the question a bit...
I am mainly looking for a way to apply any visual transformations to controls like the WindowsFormHost and the WebBrowser control.
I've found that even simple transformations do not work with these, and I was wondering if there is any trick to treating these like standard visual elements or if it is a lost cause.
Transformations on WindowsFormsHost or WebBrowser won't work, because these controls don't use the WPF rendering engine, they use GDI+.
As far as I know, the only way to achieve what you want would be to capture the control's content as an image, and manually perform the transformation on the image using GDI+ functions... It's quite easy for a simple reflection, but it can get tricky for other kinds of transformation...

Categories