Shadow like border outside Border element in Xaml - c#

I need my component to have a border that is dark closer to the component and then it fades out going away. DropShadowEffect appears on two side only (right and lower) while I want it on all four sides.
Here's what I need
While I currently have something like,
And here's my current code,
<Border x:Name="ShadowBorder" BorderThickness="1" Width="242" Height="280" Margin="5,5,5,5">
<Border.BorderBrush>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5">
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="LightBlue" Offset="1"/>
</RadialGradientBrush>
</Border.BorderBrush>
</Border>

You were on the right track using DropShadowEffect. The reason why it only blurred on two sides was because of your ShadowDepth. Set it to 0, and you will get what you want.
<Border x:Name="ShadowBorder" BorderThickness="1" Width="242" Height="280" Margin="5,5,5,5" Background="#00FFFFFF">
<Rectangle Fill="White" Width="242" Height="280"/>
<Border.Effect>
<DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="LightBlue"/>
</Border.Effect>
</Border>
Here's what it will look like:

Related

C# UWP XAML create ellipse with gradient

How is it possible to create an ellipse with gradient borders, which contains a "cropped" image? Currently i only have the ellipse with the image inside
<Ellipse Height="300" Width="300">
<Ellipse.Fill>
<ImageBrush x:Name="imageBrush" Stretch="UniformToFill"/>
</Ellipse.Fill>
</Ellipse>
Now i need to make the border transition from the image to go to transparent. Is that possible somehow in UWP XAML?
Here is an example image, which is somewhat to what i try to achieve
RadialGradientBrush from winui.
Install-Package Microsoft.UI.Xaml
xmlns:media="using:Microsoft.UI.Xaml.Media"
...
<Grid>
<Image Source="/Assets/m.jpg" Stretch="UniformToFill"/>
<Rectangle >
<Rectangle.Fill>
<media:RadialGradientBrush
Center="0.5,0.5"
GradientOrigin="0.5,0.5"
Opacity="1"
RadiusX="0.5"
RadiusY="0.5"
SpreadMethod="Pad">
<GradientStop Color="Transparent" Offset="0.6" />
<GradientStop Color="White" Offset="1.0" />
</media:RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>

What WPF control to use instead of ItemsControl to create a canvas with freely placeable items bound to a ObservableCollection?

I'm working on a GUI where the user can place items on a canvas as he wishes and work with those items. Currently I solved this with an ItemsControl as follows:
<ItemsControl ItemsSource="{Binding PlacementConfiguration.EquipmentPlacementList}" Background="AliceBlue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Position.X}"/>
<Setter Property="Canvas.Top" Value="{Binding Position.Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="150" Height="100" BorderThickness="3">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0" >
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Black" Offset="0.1"/>
<GradientStop Color="Transparent" Offset="0.1"/>
<GradientStop Color="Transparent" Offset="0.9"/>
<GradientStop Color="Black" Offset="0.9"/>
<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Label Content="TestLabel, Content will be presented here!"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
So the items are bound to a collection in the viewmodel. Each item is represented by a class instance with several properties and option. The issue with the solution above is that ItemsControl items are not selectable, which is a functionality I need.
The solution i thought was either that there is an alternative to ItemsControl that gives me the same freedom while at the same time having the ability to make items selectable, or to solve it manually using different mouse events.
Question, which solution is more feasible...or maybe if there is a completely other (better) way to go about such a issue.

WPF - How to point a setter at a child object?

I have the following xaml :
<Canvas Name="MainCanvas" Style="{StaticResource MainCanvasStyle}">
<ListView Name="MainListView" Style="{StaticResource MainListViewStyle}" ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="dnd">
<Setter TargetName="CanvasItem" Property="Canvas.Background" Value="Orange"/>
</DataTrigger>
</DataTemplate.Triggers>
<Canvas Name="CanvasItem" Height="30" Width="222" Margin="10,5,10,5">
<Canvas.Background>
<LinearGradientBrush>
<GradientStop Offset="0" Color="Orange"/>
<GradientStop Offset="1" Color="{Binding Background, ElementName=CanvasItem}"/>
</LinearGradientBrush>
</Canvas.Background>
<TextBlock Text="{Binding Number}" TextAlignment="Justify" FontSize="18" Width="150" Canvas.Top="2" Canvas.Left="10" FontWeight="Thin"/>
<TextBlock Text="{Binding Status}" TextAlignment="Right" FontSize="18" Width="50" Canvas.Top="2" Canvas.Right="5" FontWeight="DemiBold"/>
</Canvas>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Canvas>
What I'm trying to achieve is to have the second color of LinearGradientBrush in CanvasItems change depending on the current value of Items.Status.
I'd like to acomplish that by targeting the Colors inside LinearGradientBrush in CanvasItem in my setter. How could that be done?
If there are better ways of doing this then I'm open to suggestions.
Another idea I had was to handle in my ViewModel, but I'm not sure if binding them to this ListView would be possible, as my ItemsSource is already set to Items, and I don't want to modify the class that holds those.
/// While the question remains unanswered, I managed to get this to work like described by changing the Setter part to :
<Setter TargetName="CanvasItem" Property="Canvas.Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0" Color="Orange"/>
<GradientStop Offset="1" Color="Red"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
I also deleted the part with Canvas.Background in CanvasItem.
This requires me to copy and paste that snippet into every single setter which isn't as comfortable as referencing the exact color in the setter (the one in second GradientStop). There are about ten different color setters in my code so you can imagine how clumsy that looks like.
Hmm...you can't bind the Color of a GradientStop to the same LinearGradientBrush that the GradientStop belongs to if that's what you are trying to do.
You could bind to another property though. You could either use the Tag property or define your own attached Brush property:
<DataTemplate>
<Canvas Name="CanvasItem" Height="30" Width="222" Margin="10,5,10,5">
<!-- default value -->
<Canvas.Tag>
<SolidColorBrush>Green</SolidColorBrush>
</Canvas.Tag>
<Canvas.Background>
<LinearGradientBrush>
<GradientStop Offset="0" Color="Orange"/>
<GradientStop Offset="1" Color="{Binding Tag.Color, ElementName=CanvasItem}"/>
</LinearGradientBrush>
</Canvas.Background>
<TextBlock Text="Number" TextAlignment="Justify" FontSize="18" Width="150" Canvas.Top="2" Canvas.Left="10" FontWeight="Thin"/>
<TextBlock Text="Status" TextAlignment="Right" FontSize="18" Width="50" Canvas.Top="2" Canvas.Right="5" FontWeight="DemiBold"/>
</Canvas>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="dnd">
<Setter TargetName="CanvasItem" Property="Tag">
<Setter.Value>
<SolidColorBrush>Orange</SolidColorBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
I don't follow what your intention is here so I don't know whether this is a good idea or not.
But you seem to want to do it so...
You can name a colour in a gradientstop:
<LinearGradientBrush>
<GradientStop Offset="0" Color="Orange"/>
<GradientStop Offset="1">
<GradientStop.Color x:Name="MyColour">Red</GradientStop.Color>
</GradientStop>
</LinearGradientBrush>
Maybe that lineargradient could be a resource or use a dynamicresource colour and you change that out using a trigger if this is used in numerous placed.
Path syntax is really fiddly to do manually and some prefer to use blend for that sort of thing. Far less headaches. As I said, I don't really follow what you want to do here so I don't know what should be set by what from where.
Here's an example of what one looks like though:
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"
Which is referencing the rotatetransform in this:
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</ContentControl.RenderTransform>

Color inversion in XAML

In my WP8 application I want to make a color inversion effect. I have no idea what tools I should use so I'll just explain what I want in a very general terms.
How it is supposed to work: say I have a UserControl that consists of black rectangle and some white text on top of it. I want to apply something to that user control that will invert colors of a part of UserControl that it covers. Some invisible rectangle that spans say 50% of UserControl and in that area background will be white and text will be black. I want it to be dynamic so I can change the area it covers at runtime.
Here's an image to illustrate this:
Inversion effect applied to a half of control.
I believe it's possible to achieve this by using two controls with same text, inverted colors and opacity mask but I wonder if this can be done in a more clean and direct way?
I think what you're looking for ideally would either be two TextBlocks with OpacityMask applied to the one on top like;
<Grid MaxWidth="100">
<TextBlock Text="Hey check it out we can change object gradients! yay!" Foreground="Red"
TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="Hey check it out we can change object gradients! yay!" Foreground="Blue"
TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.OpacityMask>
<LinearGradientBrush StartPoint="0.1,0.1" EndPoint="0.75,0.75">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.322" Color="Black"/>
<GradientStop Offset="0.739" Color="Transparent"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</TextBlock.OpacityMask>
</TextBlock>
</Grid>
Or you could just apply a LinearGradientBrush directly to the Foreground (or Background of other element) itself like;
<Border Width="100" Height="50">
<Border.Background>
<LinearGradientBrush StartPoint="0.062,0.552" EndPoint="0.835,0.548">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.5" Color="White"/>
<GradientStop Offset="0.5" Color="Black"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<TextBlock Text="Hello World!" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Foreground>
<LinearGradientBrush StartPoint="0.1,0.1" EndPoint="0.75,0.75">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.5" Color="Black"/>
<GradientStop Offset="0.5" Color="White"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
</Border>
or gettin 80's style fancy;
<Border Width="100" Height="50">
<Border.Background>
<LinearGradientBrush StartPoint="0.472,0.047" EndPoint="0.47,0.942">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.541" Color="White"/>
<GradientStop Offset="0.548" Color="Black"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<TextBlock Text="Hello World!" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Foreground>
<LinearGradientBrush StartPoint="0.472,0.047" EndPoint="0.47,0.942">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.631" Color="Black"/>
<GradientStop Offset="0.635" Color="White"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
</Border>
Give that a shot, hope this helps.

Scale ItemsControl Rectangle based on Grid width

EDIT:
I had hex value(string) that i converted to a Brush hence it did not take my color the following like takes my colors succesfully:
(Color)ColorConverter.ConvertFromString(colorArray[0])
The only problem remaining is the scaling (with colors).
My color bars seem to be transparent (once again) but now with the proper color attached to each bar. Also at start up of my program all the 6 bars displayed (but they should not get displayed because it has no value yet).
Code:
<Border Height="30" Margin="15" Grid.RowSpan="6" >
<Border.Background>
<LinearGradientBrush StartPoint="0.0,0" EndPoint="1.0,0">
<GradientStopCollection>
<GradientStop Offset="0.0" Color="{Binding FillBar, UpdateSourceTrigger=PropertyChanged}" />
<GradientStop Offset="{Binding Value, UpdateSourceTrigger=PropertyChanged}" />
</GradientStopCollection>
</LinearGradientBrush>
</Border.Background>
</Border>
How exactly do i get rid of the transparent color fading at the middle/end of the bar?
When i try adding the same color to the second Offset i am getting Full length bars (100%) and the scaling is nullified again.
On a sudden there is also a left empty part of the control. When the control is not turned 180 degrees this behavior is not happening at all!
I have a ItemsControl that uses a DataTemplate so the items get shown as rectangles.
The itemsControl is also turned around so the rectangles show in the right direction.
<DataTemplate x:Key="GrafiekItemTemplate">
<Border Width="Auto" Height="Auto">
<Grid>
<Rectangle StrokeThickness="0" Height="30"
Margin="15"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Width="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
Fill="{Binding Fill, UpdateSourceTrigger=PropertyChanged}">
<Rectangle.LayoutTransform>
<ScaleTransform ScaleX="20" />
</Rectangle.LayoutTransform>
</Rectangle>
</Grid>
</Border>
</DataTemplate>
<ItemsControl x:Name="icGrafiek"
Margin="-484,3,0,0"
ItemsSource="{Binding Source={StaticResource Grafiek}}"
ItemTemplate="{DynamicResource GrafiekItemTemplate}"
RenderTransformOrigin="1,0.5" Grid.RowSpan="6">
<ItemsControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="-1" ScaleX="1"/>
<SkewTransform AngleY="0" AngleX="0"/>
<RotateTransform Angle="180"/>
<TranslateTransform/>
</TransformGroup>
</ItemsControl.RenderTransform>
</ItemsControl>
The binding Fill give the size of those bars (rectangles).
The itemsControl itself is placed inside a Grid with 2 columns and 6 rows.
I have set the control its rowspan to 6 and the columnspan to 1.
What i want to achieve:
The largest value of the itemsControl should take the entire length of the second column of the grid. Currently i am doing some calculations (this returns a list with values) to pass to the Fill binding and i multiply this result by for example 100 or 1000. But that is hard coded which i want to avoid.
How can i make sure these lengths are dynamically instead of filling them up with a value that i multiply with 2000 to fill my screen. For example the size of a 2nd column in a Grid.
I also have Blend available to work with the layout of this.
1) don't use rectangle, a Border is enough (Borders have a fill), and Borders have content.
2) use normalized value in your binding NValue = Value/MaxValue (between 0.0 and 1.0)
3) you can achieve what you want in two ways :
1) with a grid in your DataTemplate with two columns.
The first Column Width is bound to NormalizedValue (unit is stars (*)) and the other one
to (1-NormalizedValue) (unit is stars also (*)).
Have your ViewModel return you SWNVAlue = NValue as a star width (new GridLength(NValue,GridUnitType.Star)) or write a converter to have a star width from a double.
2) with a Border filling all the space, and a gradientBrush that stop at normalized Value :
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1.0,0">
<GradientStopCollection>
<GradientStop Offset="0.0" Color="#fff" />
<GradientStop Offset="{Binding NormalizedValue}" Color="#fff" />
<GradientStop Offset="{Binding NormalizedValue}" Color="#000" />
<GradientStop Offset="1" Color="#000" />
</GradientStopCollection>
</LinearGradientBrush>
</Border.Background>
(example makes white rectangles on a blak background.)
4) you don't need to rotate/flip. Use (1-NValue) instead of NValue, or left align, or...
but you don't need to :=)
Edit : if you need to have your 'rectangles' all aligned on the right, and starting
at a different X, for example with the GradientStopCollection way, just use (1-NormalizedValue)
and swap colors :
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1.0,0">
<GradientStopCollection>
<GradientStop Offset="0.0" Color="#000" />
<GradientStop Offset="{Binding OneMinusNormalizedValue}" Color="#000" />
<GradientStop Offset="{Binding OneMinusNormalizedValue}" Color="#fff" />
<GradientStop Offset="1" Color="#fff" />
</GradientStopCollection>
</LinearGradientBrush>
</Border.Background>
in fact same goes for the grid solution.

Categories

Resources