How do I solve this strange DropShadow issue in UWP Composition? - c#

I'm getting undesirable effects when using a drop shadow in composition. To replicate this problem, follow these steps:
Step 1: create a new UWP project and target Windows 10 Fall Creators Update (10.0; Build 16299)
Step 2: copy the following into MainPage.xaml
<Page x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Canvas x:Name="_shadow" Width="500" Height="500" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Canvas x:Name="_shadowSource" Width="500" Height="500" VerticalAlignment="Top" HorizontalAlignment="Left">
<Ellipse Width="50" Height="50" Fill="DarkOrange" Canvas.Top="50" Canvas.Left="50"/>
<Ellipse Width="50" Height="50" Fill="Aquamarine" Canvas.Top="100" Canvas.Left="100"/>
<Ellipse Width="50" Height="50" Fill="Crimson" Canvas.Top="150" Canvas.Left="150"/>
<Ellipse Width="50" Height="50" Fill="BlueViolet" Canvas.Top="200" Canvas.Left="200"/>
<Ellipse Width="50" Height="50" Fill="DarkGreen" Canvas.Top="250" Canvas.Left="250"/>
<Ellipse Width="50" Height="50" Fill="Gold" Canvas.Top="300" Canvas.Left="300"/>
<Ellipse Width="50" Height="50" Fill="MediumAquamarine" Canvas.Top="350" Canvas.Left="350"/>
<Ellipse Width="50" Height="50" Fill="Violet" Canvas.Top="400" Canvas.Left="400"/>
<Ellipse Width="50" Height="50" Fill="LightSeaGreen" Canvas.Top="450" Canvas.Left="450"/>
</Canvas>
</Grid>
</Page>
Step 3: copy the following into MainPage.xaml.cs
using System.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Hosting;
namespace App1
{
public sealed partial class MainPage
{
public MainPage()
{
InitializeComponent();
var compositor = Window.Current.Compositor;
var shadow = compositor.CreateDropShadow();
var layer = compositor.CreateLayerVisual();
shadow.SourcePolicy = CompositionDropShadowSourcePolicy.InheritFromVisualContent;
layer.Shadow = shadow;
layer.Size = new Vector2(500, 500);
var visual = ElementCompositionPreview.GetElementVisual(_shadowSource);
layer.Children.InsertAtBottom(visual);
ElementCompositionPreview.SetElementChildVisual(_shadow, layer);
}
}
}
The contents of _shadowSource is moved to a new layer with a shadow set as InheritFromVisualContent. When the app loads, you'll see the shadows render fine, but resizing the app creates visual glitches.
Here's what happens when you comment out the line //layer.Shadow = shadow;
What's happening here? Why does a shadow cause this?

When your window height is less than 500, the _shadowSource height is still 500 because you have Width="500" Height="500" in your XAML. So it’s clipped and only upper portion is visible.
But you add your shadow to another element named _shadow. This one doesn’t have fixed size, so it resizes to the size of your window, i.e. no clipping happens. That’s why your circles get distorted to ellipses, and you see these nasty artifacts in the lower portion of your window — if your shadow would be laid out correctly, these parts of the layer would be clipped away and invisible.

I used the DropShadowPanel control of UWP Community Toolkit to apply drop shadow for the Ellipse. It worked well.
You could try the following:
<Page
...
xmlns:control="using:Microsoft.Toolkit.Uwp.UI.Controls"
...
>
<Canvas VerticalAlignment="Top" HorizontalAlignment="Left">
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="50" Canvas.Left="50"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="DarkOrange" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="100" Canvas.Left="100"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="Aquamarine" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="150" Canvas.Left="150"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="Crimson" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="200" Canvas.Left="200"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="BlueViolet" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="250" Canvas.Left="250"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="DarkGreen" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="300" Canvas.Left="300"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="Gold" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="350" Canvas.Left="350"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="MediumAquamarine" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="400" Canvas.Left="400"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="Violet" />
</control:DropShadowPanel>
<control:DropShadowPanel BlurRadius="4.0" Canvas.Top="450" Canvas.Left="450"
ShadowOpacity="0.7"
OffsetX="5.0"
OffsetY="5.0"
Color="Black">
<Ellipse Width="50" Height="50" Fill="LightSeaGreen" />
</control:DropShadowPanel>
</Canvas>
I check its source code, I found that it will update shadow size and other things when the app window is resized. So, maybe, it's the key point. You could
refer to its source code to extend your own code. Or you could directly use the DropShadowPanel control.

Related

Add "File" name on RibbonApplicationMenu in WPF Ribbon

I am new in making WPF projects.
I searched on how to add Text in RibbonApplicationMenu maybe it looks that, there's the same questions to this in this site but trust me I implemented it but didn't works in me.
I've tried putting a "File" name in my <RibbonApplicationMenu>, I put Label="File" but it doesn't work. What can I try next?
Here's my XAML code:
<Ribbon x:Name="Ribbon">
<Ribbon.TitleTemplate>
<DataTemplate >
<TextBlock x:Name="FrontPageTitle" TextAlignment="Center" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Ribbon}}, Path=Title}" Width="{Binding ElementName=RibbonWindow, Path=ActualWidth}" />
</DataTemplate>
</Ribbon.TitleTemplate>
<Ribbon.HelpPaneContent>
<RibbonButton SmallImageSource="pack://application:,,,/MYSEP;component/Images/window.png" />
</Ribbon.HelpPaneContent>
<Ribbon.QuickAccessToolBar>
<RibbonQuickAccessToolBar>
<RibbonButton x:Name="QATButton1"
SmallImageSource="pack://application:,,,/MYSEP;component/Images/window.png" />
<RibbonButton x:Name="QATButton2"
SmallImageSource="pack://application:,,,/MYSEP;component/Images/window.png" />
</RibbonQuickAccessToolBar>
</Ribbon.QuickAccessToolBar>
<Ribbon.ApplicationMenu>
<RibbonApplicationMenu Label="File">
<RibbonApplicationMenuItem Header="New Design Project"
x:Name="NewDesignProject"
ImageSource="pack://application:,,,/MYSEP;component/Images/newProject.png" Click="AddNewDesign"/>
<RibbonApplicationMenuItem Header="New Rating Project"
x:Name="NewRatingProject"
ImageSource="pack://application:,,,/MYSEP;component/Images/newProject.png" Click="AddNewRating"/>
<RibbonApplicationMenuItem Header="Open..."
x:Name="Open"
ImageSource="pack://application:,,,/MYSEP;component/Images/open.png" Click="OpenMysepProject"/>
</RibbonApplicationMenu>
</Ribbon.ApplicationMenu>
<RibbonTab x:Name="HomeTab"
Header="Home">
<RibbonGroup x:Name="Group1"
Header="Project">
<RibbonButton x:Name="Button1"
LargeImageSource="pack://application:,,,/MYSEP;component/Images/manageProject.png"
Label="Manage Project" />
</RibbonGroup>
<RibbonGroup x:Name="Group2"
Header="Vessel">
<RibbonButton x:Name="Button2"
LargeImageSource="pack://application:,,,/MYSEP;component/Images/addVessel.png"
Label="Add Vessel Design Mode" />
<RibbonButton x:Name="Button3"
LargeImageSource="pack://application:,,,/MYSEP;component/Images/info.png"
Label="Add Vessel Rating Mode" />
<RibbonButton x:Name="Button4"
LargeImageSource="pack://application:,,,/MYSEP;component/Images/delete.png"
Label="Delete Vessel" />
</RibbonGroup>
</RibbonTab>
</Ribbon>
Just like this image:
A number of possible (though complicated) solutions here:
How to set text at the head of a RibbonApplicationMenu
EDIT
I tested myself, just add this immediately after <RibbonApplicationMenu>:
<RibbonApplicationMenu.SmallImageSource>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,20,20"></RectangleGeometry>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<VisualBrush Stretch="Uniform">
<VisualBrush.Visual>
<TextBlock Text="File" FontSize="16" Foreground="White" />
</VisualBrush.Visual>
</VisualBrush>
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</RibbonApplicationMenu.SmallImageSource>
And here you go:

Placing a textblock in WIndows Phone 7 application

I am building an application in WIndows phone 7. I have the following xaml:
<Rectangle Fill="White" HorizontalAlignment="Left" Height="123" Margin="273,173,0,0"
Stroke="Black" VerticalAlignment="Top" Width="172" RadiusX="20" RadiusY="20 />
Now here i want to insert a text and also make this clickable in order to navigate to a new page. How to do this. Please share some code
<Rectangle Fill="White" HorizontalAlignment="Left" Height="123" Margin="273,173,0,0"
Stroke="Black" VerticalAlignment="Top" Width="172" RadiusX="20" RadiusY="20"
MouseDown="SomeFunctionInCodeBehindToTakeYouToANewPage" />
<TextBlock HorizontalAlignment="Left" IsHitTestVisible="False" Margin="340,222,0,0"
VerticalAlignment="Top" Text="I Like Pie" />

How can I show the plot points in Oxyplot for a line Graph?

Here is the xaml code to my graph:
<oxy:Plot HorizontalAlignment="Left"
Height="222"
Margin="0,49,0,0"
VerticalAlignment="Top"
Width="870"
Background="Transparent"
PlotAreaBorderColor="White"
LegendBorder="Transparent"
Name="viewCountPlot"
Title="Videos Watched"
TextColor="White" IsLegendVisible="False" IsManipulationEnabled="False" IsMouseWheelEnabled="False">
<oxy:Plot.Axes>
<oxy:DateTimeAxis Name="datetimeAxis" Position="Bottom" MajorGridlineColor="#40FFFFFF" TicklineColor="White" StringFormat="M/d/yy" IntervalType="Days" ShowMinorTicks="False"/>
</oxy:Plot.Axes>
<oxy:Plot.Series>
<oxy:LineSeries
Name="viewCountSeries"
Title="Videos Viewed"
DataFieldX="Date"
DataFieldY="Value"
Color="#CCFA6800"
StrokeThickness="2"
TrackerFormatString="Date: {2:M/d/yy}
Value: {4}"
ItemsSource="{Binding PlotItems}" MarkerStroke="#FFFDFDFD" />
</oxy:Plot.Series>
<oxy:Plot.DefaultTrackerTemplate>
<ControlTemplate>
<Canvas>
<Grid Canvas.Left="{Binding Position.X}" Canvas.Top="{Binding Position.Y}">
<Ellipse Fill="White" Width="12" Height="12" HorizontalAlignment="Left" VerticalAlignment="Top">
<Ellipse.RenderTransform>
<TranslateTransform X="-6" Y="-6" />
</Ellipse.RenderTransform>
</Ellipse>
<TextBlock Foreground="{DynamicResource OrangeTextColor}" Text="{Binding}" Margin="-60 -40 0 0" />
</Grid>
</Canvas>
</ControlTemplate>
</oxy:Plot.DefaultTrackerTemplate>
</oxy:Plot>
In the plot Series is there any way to show the plot points as circles or something of that nature?
Here is an example image of what I mean, each plot point has a small circle associated with it:
From the linked discussion:
This should be covered by the Marker* properties in the LineSeries
See examples in the Example browser.
It looks like you have to set MarkerFill and MarkerType. To show only markers (and no line), set the Color to Transparent.
<oxy:LineSeries ItemsSource="{Binding MyDataPoints}"
Color="Transparent"
MarkerFill="SteelBlue"
MarkerType="Circle" />
Answered on the Oxyplot forums for those who find this.
https://oxyplot.codeplex.com/discussions/528893

Unable to get to "ScrollStates" in ScrollViewer Control

I'm having a lot of trouble trying to get this working, and was hoping someone could help.
I have a ScrollViewer in my WindowsPhone app, and I'm trying to emulate a similar control to the "Date/Time Chooser" that you'd see in the native Calendar app. So my ScrollViewer contains a StackPanel with multiple square Canvases with rectangles and TextBlocks. My intent is to watch the "ScrollStates", and when the VisualState changes to "NotScrolling", I'd then check the VerticalOffset of the ScrollViewer and animate a slide to the nearest "snap-to" position (ie. aligning the square to the correct/middle position).
<ScrollViewer Name="sv" Width="100" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Disabled" Loaded="ScrollViewer_Loaded">
<StackPanel>
<Canvas MaxWidth="77" MaxHeight="80" MinWidth="80" MinHeight="80" Margin="3">
<Rectangle Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="3" Width="80" Height="80" />
<TextBlock Text="1" FontSize="36" FontWeight="Bold" TextAlignment="Center" HorizontalAlignment="Center" Width="70" Canvas.Left="6" Canvas.Top="14" LineHeight="48" />
</Canvas>
<Canvas MaxWidth="77" MaxHeight="80" MinWidth="80" MinHeight="80" Margin="3">
<Rectangle Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="3" Width="80" Height="80" />
<TextBlock Text="2" FontSize="36" FontWeight="Bold" TextAlignment="Center" HorizontalAlignment="Center" Width="70" Canvas.Left="6" Canvas.Top="14" LineHeight="48" />
</Canvas>
<Canvas MaxWidth="77" MaxHeight="80" MinWidth="80" MinHeight="80" Margin="3">
<Rectangle Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="3" Width="80" Height="80" />
<TextBlock Text="3" FontSize="36" FontWeight="Bold" TextAlignment="Center" HorizontalAlignment="Center" Width="70" Canvas.Left="6" Canvas.Top="14" LineHeight="48" />
</Canvas>
...
</StackPanel>
</ScrollViewer>
I've been looking at various examples that hook into the VisualStates, like http://blogs.msdn.com/b/ptorr/archive/2010/07/23/how-to-detect-when-a-list-is-scrolling-or-not.aspx ; http://developingfor.net/2009/02/16/fun-with-the-wpf-scrollviewer/ ; http://blogs.msdn.com/b/slmperf/archive/2011/06/30/windows-phone-mango-change-listbox-how-to-detect-compression-end-of-scroll-states.aspx ... all seem to have similar code to this:
// Visual States are always on the first child of the control template
FrameworkElement element = VisualTreeHelper.GetChild(sv, 0) as FrameworkElement;
... which then goes on to seek out VisualStateGroup group = FindVisualState(element, "ScrollStates");, from which they can hook an Event to when it changes.
However... whenever I try doing the VisualTreeHelper.GetChild(sv,0) as FrameworkElement, the app crashes with an exception of type 'System.ArgumentOutOfRangeException'. If I output VisualTreeHelper.GetChildrenCount(sv), it is always "0". How is it seemingly working for everyone else? 8)
Any help would be greatly appreciated. Thanks!
(As an alternative, has anyone made this kind of "Select Box" already in a reusable control I could use instead of trying to reinvent it?)
Did you wait till the scrollviewer's Loaded event fires before trying to get the scrollviewer children??

Combining images in rectangle, if i hide rectangle, images should be hidden too

I am using a rectangle and putting emotion images in it, and i want to do is if I make the rectangle hidden, the emotion images in it should be hidden.
I am attaching an image for help in it.
Please let me know which property should I use for getting this, in Windows Forms if we use panel, this can be done automatically. But in WPF C#, this is not done automatically.
Here is the code
<Rectangle Grid.ColumnSpan="2" Height="71" HorizontalAlignment="Left" Margin="226,262,0,0" Name="rectangle2" Stroke="Black" VerticalAlignment="Top" Width="192" Fill="#B5101010" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="229,266,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="28" Source="/WPFTEST;component/Images/emo/emotion_evilgrin.png" MouseUp="image1_MouseUp_1" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="264,266,0,0" Name="image2" Source="/WPFTEST;component/Images/emo/emotion_grin.png" Stretch="Fill" VerticalAlignment="Top" Width="28" MouseUp="image2_MouseUp" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="34,299,0,0" Name="image4" Source="/WPFTEST;component/Images/emo/emotion_tongue.png" Stretch="Fill" VerticalAlignment="Top" Width="28" Grid.Column="1" MouseUp="image4_MouseUp" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="68,266,0,0" Name="image5" Source="/WPFTEST;component/Images/emo/emotion_suprised.png" Stretch="Fill" VerticalAlignment="Top" Width="28" Grid.Column="1" MouseUp="image5_MouseUp" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="34,266,0,0" Name="image6" Source="/WPFTEST;component/Images/emo/emotion_smile.png" Stretch="Fill" VerticalAlignment="Top" Width="28" Grid.Column="1" MouseUp="image6_MouseUp" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="0,266,0,0" Name="image7" Source="/WPFTEST;component/Images/emo/emotion_happy.png" Stretch="Fill" VerticalAlignment="Top" Width="28" Grid.Column="1" MouseUp="image7_MouseUp" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="0,299,0,0" Name="image8" Source="/WPFTEST;component/Images/emo/emotion_wink.png" Stretch="Fill" VerticalAlignment="Top" Width="28" Grid.Column="1" MouseUp="image8_MouseUp" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="230,299,0,0" Name="image9" Source="/WPFTEST;component/Images/emo/emotion_unhappy.png" Stretch="Fill" VerticalAlignment="Top" Width="28" MouseUp="image9_MouseUp" Visibility="Hidden" />
<Image Height="27" HorizontalAlignment="Left" Margin="265,299,0,0" Name="image10" Source="/WPFTEST;component/Images/emo/emotion_waii.png" Stretch="Fill" VerticalAlignment="Top" Width="28" MouseUp="image10_MouseUp" Visibility="Hidden" />
I know that it is not under the rectangle tag, but if i add images under rectangle tag then it causes error.
Thanks
Atif
If those icons are part of the "rectangle" which should be an ItemsControl or panel of some sort, the icons will hide if the parent container is hidden (Visibility = Visibility.Hidden/Collapsed).
Edit: The images are not part of the rectangle they are just placed on top using horrible margin abusing code.
There is no relationship between the rectangle and the icons. As i said, the icons need to be added as children of a container. (e.g. ItemsControl with WrapPanel as ItemsPanel) Surely winforms would not hide the icons either if they are not part of an owning container...
If you want to leave your code as is and not have to change those margins you can just bind the Visibility property of the icons to the Visibility property of the rectangle.
Visibility="{Binding Visibility, ElementName=rectangle2}"

Categories