How do I use Light on a Control in WPF? - c#

I have a custom user control, and I'd like to add some light effects to the custom control. I was trying to go for a light to "sweep" the control when the mouse enters the control. But I'm slightly lost as to how to use WPF lights. I can use them on custom geometry I define, but I can't seem to get them to work on standard controls.
This is my xaml code for the custom control:
<UserControl x:Name="CActionTile" x:Class="App.ActionTile"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:App" Background="{DynamicResource ActionTileBackgroundBrush}"
BorderThickness="0,0,0,0.5" BorderBrush="DarkSlateGray"
mc:Ignorable="d" Height="80" d:DesignWidth="388">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center">
<Run FontFamily="Segoe UI" FontWeight="Thin" FontSize="28"
Foreground="{DynamicResource ActionLabelBrush}" Text="{Binding Label, ElementName=CActionTile}" />
<LineBreak/>
<Run FontFamily="Segoe UI" FontWeight="Normal" FontSize="12"
Foreground="{DynamicResource ActionSubLabelBrush}" Text="{Binding SubLabel, ElementName=CActionTile}" />
</TextBlock>
<!-- This is where I'm kinda stuck... not sure what to do from here... -->
<Viewport3D x:Name="vp1">
<Viewport3D.Camera>
<PerspectiveCamera LookDirection="0,0,-1" Position="0,0,5" />
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<AmbientLight Color="White" />
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
</UserControl>
Basically I'm trying to get this UWP Composition effect (https://github.com/microsoft/WindowsCompositionSamples/tree/master/SampleGallery/Samples/SDK%2014393/TextShimmer) to work in my WPF application. I'm pretty sure I can figure out the sweep effect when the pointer enters the control, but I need some help getting light effects to show on the controls themselves.

Related

WPF ItemTemplate Causing ListBox Content Size Issue

In a WPF project, I have a ListBox that renders correctly if I manually insert items in XAML, e.g.:
<ListBoxItem>
<Grid Background="#7F271043" Width="200" Height="200">
<Grid.RowDefinitions>
<RowDefinition Height="110" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="Logo-40p.png" HorizontalAlignment="Center" Margin="10,10,10,10" />
<TextBlock Grid.Row="1" Text="Test Item" Foreground="White" Margin="10,0,10,0" FontSize="16" VerticalAlignment="Center" />
<local:Rating Grid.Row="2" HorizontalAlignment="Left" Height="24" Margin="10,0,0,0" VerticalAlignment="Center" Width="130" SelectedValue="4" IsReadOnly="True" />
<TextBlock Grid.Row="2" Text="Free" Foreground="#FF969292" Margin="0,0,10,0" FontSize="14" HorizontalAlignment="Right" VerticalAlignment="Center" />
</Grid>
</ListBoxItem>
The bottom of the ListBoxItem looks like:
However, the moment I swap out <ListBoxItem> for:
<ListBox.ItemTemplate>
<DataTemplate>
Even if I keep everything else identical, it creates a sizing problem with my rating control that I'm unable to fix (doesn't respond to manual size or stretch settings):
Any thoughts on how to address this? Do ItemTemplate / DataTemplate do something that might cause a control to not respect the size manually set or set by the grid row it's in?
Managed to fix this - it seems that a manually defined ListBoxItem in XAML behaves differently from the output of an ItemTemplate / DataTemplate.
My rating user control had a set height and width specified that were overridden by the implementation XAML (height/width/stretch) inside a ListBoxItem but not inside a ItemTemplate / DataTemplate:
mc:Ignorable="d" Height="750" Width="4070" MouseLeave="UserControl_MouseLeave">
So I instead changed Height / Width to DesignHeight / DesignWidth to fix the issue:
mc:Ignorable="d" d:DesignHeight="750" d:DesignWidth="4070" MouseLeave="UserControl_MouseLeave">

Restyling UWP Toolkit Expander Arrow

I'm trying to restyle the Expander control from the Windows Community Toolkit, changing the default ">" symbol to a filled arrow (kind of like a Play button). Following the accepted answer in this question, I copied the default style from the Community Toolkit github repo, and pasted it into a ResourceDictionary (named CustomStyles.xaml), then changed the FontIcon Glyph property from  to . I've referenced that ResourceDictionary in the Page.Resources section, and then bound the new style to the Expander's HeaderTemplate property with a StaticResource reference. Everything should work, but something is causing it to fail.
The exception being thrown is of no help either, as the error displays the message Failed to assign to property 'Microsoft.Toolkit.Uwp.UI.Controls.HeaderedContentControl.HeaderTemplate'. The text associated with this error code could not be found.
Can someone help with this please?
MainPage.xaml
<Page
x:Class="SharpFTP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SharpFTP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CustomStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" MinHeight="40" />
</Grid.RowDefinitions>
<StackPanel x:Name="itemsPanel" Grid.Column="0" Grid.Row="0">
<toolkit:Expander Header="Favorites" ExpandDirection="Down" HeaderTemplate="{StaticResource expanderFullArrowStyle}">
</toolkit:Expander>
<TextBlock Text="Favorites" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="Connected to " Style="{ThemeResource SubtitleTextBlockStyle}" Foreground="LightGray" />
<TextBlock Text=" 10.3.12.128" Style="{ThemeResource SubtitleTextBlockStyle}" Foreground="White"/>
</StackPanel>
<AppBarSeparator Width="{Binding ActualWidth, ElementName=itemsPanel}" Height="2" Foreground="LightGray" />
</StackPanel>
</Grid>
ResourceDictionary XAML
I've included only the modified portion as the full style is 300 lines long. The full default Expander style can be found here
<FontIcon x:Name="Arrow" Margin="12" FontFamily="Segoe MDL2 Assets" FontSize="12"
Glyph="" RenderTransformOrigin="0.5,0.5">
<FontIcon.RenderTransform>
<RotateTransform />
</FontIcon.RenderTransform>
</FontIcon>
The cause of your error should be a type mismatch.
You have modified the default style of Expender, then expanderFullArrowStyle should not be used on HeaderTemplate. Please try this:
<toolkit:Expander Header="Favorites" ExpandDirection="Down" Style="{StaticResource expanderFullArrowStyle}">
</toolkit:Expander>

WPF - change text anchor in Canvas

Here's some XAML:
<Grid Width="200" Height="200">
<Canvas Background="Beige">
<Line X1="0" X2="200" Y1="100" Y2="100" Stroke="Black"/>
<Line X1="100" X2="100" Y1="0" Y2="200" Stroke="Black"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Margin="2">
<TextBlock.RenderTransform>
<TranslateTransform X="100" Y="100"/>
</TextBlock.RenderTransform>
hello world1
<LineBreak/>
hello world2
<LineBreak/>
hello world3
</TextBlock>
</Canvas>
</Grid>
I want the text to appear in the top-right quadrant of my Canvas instead of the bottom right quadrant.
Is it possible to do in WPF?
Currently the text is drawn from topleft to bottomright, I would like it do be drawn from bottomleft to topright.
I couldn't find an answer on the internet that works inside a Canvas.
In my production code the text should be able to be of any length and height.
Edit:
I've been asked to provide a fully working sample, so here goes:
XAML:
<Window x:Class="WpfApp1.MainWindow"
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"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<!--The drawing area can be anything, a grid, a panel, a canvas... Can't just use specific alignment tools so I have to use a Transform-->
<Grid x:Name="DrawingArea" Background="Beige" MouseMove="UIElement_OnMouseMove">
<TextBlock x:Name="TextBlock" Margin="2">
hello world1
<LineBreak/>
hello world2
<LineBreak/>
hello world3
</TextBlock>
</Grid>
</Grid>
</Window>
Code behind:
using System.Windows.Input;
using System.Windows.Media;
namespace WpfApp1
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
{
var mousePos = e.GetPosition(DrawingArea);
TextBlock.RenderTransform = new TranslateTransform(mousePos.X, mousePos.Y);
}
}
}
Currently the text appears below the default Windows mouse cursor, I'd like it to appear above the default Windows mouse cursor.
You see it in the lower right part because of the TranslateTransform. You set it to X=100, Y=100. If you set Y=0 it should be on the top.
But you should consider some things with this code:
Why use TranslateTransform inside a canvas? You can just add the Canvas.Top and Canvas.Left properties to the TextBlock and that should do it. Use the TranslateTransform only if you're looking to animate the element, and even then, it's more convenient to set it to (0, 0), and change it only during the animation.
Why are you using the canvas at all? And more over why inside a Grid? You should be able to achieve what you want by using a single Grid, or even a DockPanel. A Canvas is used only for graphics, that should always remain in the same place. There are better solutions for data, especially if it's supposed to change during runtime.
If you want a cross in the background of your grid, you can try something like this:
<Grid
Width="200"
Height="200"
Background="Beige">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Line
X1="0"
X2="200"
Y1="100"
Y2="100"
Stroke="Black"
Grid.RowSpan="2"
Grid.ColumnSpan="2"/>
<Line
X1="100"
X2="100"
Y1="0"
Y2="200"
Stroke="Black"
Grid.RowSpan="2"
Grid.ColumnSpan="2"/>
<TextBlock
VerticalAlignment="Center"
HorizontalAlignment="Center" Margin="2"
Grid.Row="0"
Grid.Column="1">
hello world1
<LineBreak/>
hello world2
<LineBreak/>
hello world3
</TextBlock>
</Grid>
Add a grid to your canvas and set the properties
HorizontalAlignment="Right"
VerticalAlignment="Top"
<Canvas x:Name="newCanvas">
<Grid>
<Label Content="Hello World!"
HorizontalAlignment="Right"
VerticalAlignment="Top"
/>
</Grid>

Why is my DataGrid going off screen no matter what solution I try?

I am new to C# and WPF trying to get what I should think is a simple thing, but it doesn't work.
I have a data grid being populated by SQL, and no matter what I try, I can't get the Height of the DataGrid to stay within the window. It always just extends down. I want it to be dynamic to the window size.
My very simple code is below, or at least this most recent iteration.
<Page x:Class="TMSMaintenance.PaymentError"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TMSMaintenance"
Title="PaymentError">
<!--<DataGrid Name="MydataGrid" CanUserAddRows="False" SelectionMode="Single" />-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" VerticalAlignment="Stretch" >
<DataGrid x:Name="MydataGrid"
VerticalAlignment="Stretch"
MinHeight="100"
VerticalScrollBarVisibility="Auto" VerticalContentAlignment="Stretch">
</DataGrid>
</DockPanel>
</Grid>
</Page>
I have tried wrapping in a ScrollView - it didn't work. I tried setting the Height by binding it to the window - it didn't work. I have tried the Grid.RowDefinition Height = "*" and "1*" - it didn't work. VerticalAlignment = "Stretch" also didn't work.
So what am I missing?
Edit: Maybe I should also say that this is on a Page file called within a frame tag. Not sure if it makes a difference here.
<StackPanel CanVerticallyScroll="True" CanHorizontallyScroll="True">
<!-- Navigation -->
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<Button Content="Files Lookup" Margin="0,0,10,0"/>
<Button Content="Payment Error" Margin="0,0,10,0"/>
<Button Content="Carrier Maintenance" Margin="0,0,10,0"/>
<Button Content="Payment File" Margin="0,0,10,0" />
</StackPanel>
<ScrollViewer>
<Frame x:Name="MainFrame" NavigationUIVisibility="Hidden" ></Frame>
</ScrollViewer>
</StackPanel>
Get rid of that DockPanel. Grid is a much more flexible container for controls and you don't need to pack container into container at all. This alone should do the trick.
Good practice is to not use DockPanels at all. Never. Everything you can achieve with DockPanels can be achieved with Grids (with a bit more of coding, but it gives you more flexible solution and better maintainability of your code).
Also get rid of VerticalContentAlignment (not needed in case you described) and you don't need to define VerticalAlignment (nor HorizontalAlignment) to Stretch, since it's a default value of that property.
EDIT:
I haven't noticed the second sample of your code. Everything I wrote before still applies and will make your code better, but I think your problem is with nesting your Page in your main container (Window or whatever it is).
Try replacing:
<StackPanel CanVerticallyScroll="True" CanHorizontallyScroll="True">
<!-- Navigation -->
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<Button Content="Files Lookup" Margin="0,0,10,0"/>
<Button Content="Payment Error" Margin="0,0,10,0"/>
<Button Content="Carrier Maintenance" Margin="0,0,10,0"/>
<Button Content="Payment File" Margin="0,0,10,0" />
</StackPanel>
<ScrollViewer>
<Frame x:Name="MainFrame" NavigationUIVisibility="Hidden" ></Frame>
</ScrollViewer>
</StackPanel>
To:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Orientation="Horizontal"
Margin="0,10,0,0">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="0,0,10,0" />
</Style>
</StackPanel.Resources>
<Button Content="Files Lookup"/>
<Button Content="Payment Error"/>
<Button Content="Carrier Maintenance"/>
<Button Content="Payment File"/>
</StackPanel>
<Frame x:Name="MainFrame"
Grid.Row="1"
NavigationUIVisibility="Hidden" />
</Grid>
I have also simplified your styling on Buttons and I'd recommend you to change your Page to UserControl.

Get Fill Color of Rectangle in Coded UI for Windows Phone

I'm writing some Coded UI tests for a simple application and cannot seem to get the code to find Rectangle objects. In the specific case I have the color of the rectangle presents whether two strings match or not based on the fill color.
When trying to find the rectangle using the Coded UI Test Builder the parent object is being found instead of the rectangle. I am also seeing that the code returns that it is unable to find the rectangle when I have it search manually.
Below is the XAML for the page I am trying to test against:
<Page
x:Class="TestApp.ButtonTester"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="LayoutRoot">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Title Panel -->
<StackPanel Grid.Row="0" Margin="19,0,0,0">
<TextBlock Text="{StaticResource AppName}" Style="{ThemeResource TitleTextBlockStyle}" Margin="0,12,0,0"/>
<TextBlock Name="pageTitle" Text="Button Tester" Margin="0,-6.5,0,26.5" Style="{ThemeResource HeaderTextBlockStyle}" CharacterSpacing="{ThemeResource PivotHeaderItemCharacterSpacing}"/>
</StackPanel>
<!--TODO: Content should be placed within the following grid-->
<Grid Grid.Row="1" x:Name="ContentRoot" Margin="19,9.5,19,0">
<StackPanel Name="buttonValidator">
<TextBlock Name="verifyText" Text="Hi" HorizontalAlignment="Center" Style="{StaticResource LargeText}"/>
<Button Name="changeText" Content="Change Text" HorizontalAlignment="Center" Click="changeText_Click"/>
<TextBox Name="guessText" Text="Enter Text From Above" TextAlignment="Center" GotFocus="guessText_GotFocus" KeyDown="guessText_KeyDown"/>
<Button Name="verifyMatch" Content="Verify" HorizontalAlignment="Center" Click="verifyMatch_Click"/>
<Rectangle Name="matchAlert" Height="50" Width="50" Fill="Black" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
</Grid>
And here is the test code I currently have:
[TestMethod]
public void TestVerifyIncorrect()
{
UITestControl verifyMatch = new UITestControl(myApp);
verifyMatch.TechnologyName = "UIA";
verifyMatch.SearchProperties.Add("ControlType", "Button");
verifyMatch.SearchProperties.Add("AutomationId", "verifyMatch");
Gesture.Tap(verifyMatch);
UITestControl matchAlert = new UITestControl(myApp);
matchAlert.TechnologyName = "UIA";
matchAlert.SearchProperties.Add("ControlType", "Rectangle");
matchAlert.SearchProperties.Add("AutomationId", "matchAlert");
var fillColor = matchAlert.GetProperty("Fill");
}
I am also seeing the Test Builder unable to detect a rectangle even when it is being used as a control.
I also looked into the Rectangle class vs the Button class and it appears the first common link in their inheritance chains is with Windows.UI.Xaml.FrameworkElement. I'm unaware of what type of ojects the Coded UI is able to detect to know if that may be the cause of the issue.

Categories

Resources