WPF Play Movie on Mouse Over - wpf

Is there a way using WPF to get a video element to start playing when a user puts there mouse pointer over the element? I am wanting to make an interactive digital resource and want a clip of the movie to play when the mouse over the element to click to take them to the movie section. Any help would be great.
This is going to all be contained in a windows application.

If you're using a MediaElement to play your video, just listen for the MouseEntered Event and call Play().
Note: The LoadedBehavior property of MediaElement must be set to Manual in order to be able to interactively stop, pause, and play the media.
Here's an example:
In C# code-behind:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void mediaElement1_MouseEnter(object sender, MouseEventArgs e)
{
mediaElement1.Play();
}
private void mediaElement1_MouseLeave(object sender, MouseEventArgs e)
{
mediaElement1.Stop();
}
private void mediaElement1_Loaded(object sender, RoutedEventArgs e)
{
mediaElement1.Pause();
}
}
In XAML:
<Window x:Class="VideoTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<MediaElement Margin="12"
Name="mediaElement1"
Source="mediaFile.avi"
LoadedBehavior="Manual"
MouseEnter="mediaElement1_MouseEnter"
MouseLeave="mediaElement1_MouseLeave"
Loaded="mediaElement1_Loaded"
/>
</Grid>
</Window>

Found an issue with the
<MediaElement Margin="12"
Name="mediaElement1"
Source="mediaFile.avi"
LoadedBehavior="Manual"
MouseEnter="mediaElement1_MouseEnter"
MouseLeave="mediaElement1_MouseLeave"
Loaded="mediaElement1_Loaded"
/>
It doesnt seem to like the
Loaded="mediaElement1_Loaded"
So I changed my Initialize in my code behind to contain the
mediaElement1.Pause();
And it is working just fine.

Related

WPF not load a control

I write a very easy UserControl
here the Xaml code
<UserControl x:Name="Test1" x:Class="WpfAppXtesting.UserControl1"
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:WpfAppXtesting"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Loaded="Test1_Loaded">
<Grid x:Name="GridRoot" Background="Aqua">
<TextBlock x:Name="status" HorizontalAlignment="Left" Height="137" Margin="100,137,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="483" FontSize="48"/>
</Grid>
and here the code behind
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.GridRoot.DataContext = this;
}
private void UserControl1_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Connected":
status.Text = ((App)sender).Connected.ToString() ;
break;
}
}
private void Test1_Loaded(object sender, RoutedEventArgs e)
{
(Application.Current as App).PropertyChanged += UserControl1_PropertyChanged;
}
}
the problem is , when import this control in a Window in same project The design mode gets this error.
NullReferenceException: Object reference not set to an instance of an object.
if I run the project everything was good.
If I commented the line in Loaded method
the control was right shown in design mode.
Any Idea?
thanks
Do not assume that Application.Current is your application at design time. For example, when you are using Expression Blend, Current is Expression Blend. At design time, MainWindow is not your application's main window. Typically operations that cause a user/custome control to fail at design time include the following.
Casting Current to your custom subclass of App.
Casting MainWindow to your custom subclass of Window.
Here are two approaches to writing code for design time. The first approach is to write defensive code by checking the null condition. The second approach is to check whether design mode is active by calling the GetIsInDesignMode method. You can read about GetIsInDesignMode at here.
Solution 1:
private void Test1_Loaded(object sender, RoutedEventArgs e)
{
var app = Application.Current as App;
if( app != null)
{
app.PropertyChanged += UserControl1_PropertyChanged;
}
}
Solution 2 :
private void Test1_Loaded(object sender, RoutedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(this))
{
// Design-mode specific functionality
(Application.Current as App).PropertyChanged += UserControl1_PropertyChanged;
}
}

How to lock the orientation of WPF application

Is there an API to lock the orientation of my WPF application to run only in the landscape mode.
i could find event that could fire on orientation change, but is there a way to lock it
Microsoft.Win32.SystemEvents.DisplaySettingsChanged
I dont think there is a way in WPF to lock it, you could provide a rotation layout transformation to the root container. It is not actually locking the orientation but rotating your application. Something like this,
<Grid.RenderTransform>
<RotateTransform Angle="-90"/>
</Grid.RenderTransform>
Read here,
Layout Transformation
For anyone who arrives at this question and is left needing more detail, here is a fully detailed answer...
It appears that as tablet rotation support was done at the individual vendor level, there isn’t much support for it in Windows 7 / 8 other than detecting that there was a change in rotation. The screen can still be pseudo-locked into a landscape format with a bit of XAML sleight of hand. Here’s some sample code that I knocked up last night and tested on my tablet PC…
MainWindow.xaml
<Window x:Class="LockRotationWpf.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:LockRotationWpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5" >
<Grid.RenderTransform >
<RotateTransform Angle="{Binding Angle}" />
</Grid.RenderTransform>
<StackPanel>
<TextBlock FontSize="100" Text="Landscape"/>
<TextBlock Text="{Binding Angle}" TextAlignment="Center"/>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
using LockRotationWpf.ViewModels;
namespace LockRotationWpf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new MainWindowViewModel();
DataContext = vm;
}
}
}
ViewModels\MainWindowViewModel.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using LockRotationWpf.Annotations;
namespace LockRotationWpf.ViewModels
{
// Omit the INotifyPropertyChanged implementation if already implemented on a base ViewModel class.
public class MainWindowViewModel : INotifyPropertyChanged
{
public double _angle;
public MainWindowViewModel()
{
Microsoft.Win32.SystemEvents.DisplaySettingsChanged += DisplaySettingsChanged;
}
private void DisplaySettingsChanged(object sender, EventArgs e)
{
Angle = System.Windows.SystemParameters.PrimaryScreenHeight > System.Windows.SystemParameters.PrimaryScreenWidth ? -90 : 0;
}
public double Angle
{
get { return _angle; }
set
{
_angle = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here are a couple of screen-shots that show the change in orientation. If you’re running an App full screen you won’t get the window chrome and you’d be unaware that the screen had actually rotated. Any on-screen keyboard which opens in response to a text input will of course still pop-up in the portrait position, but the fact that the content is always landscape should give the operator enough of a hint to turn the tablet around for input.
I hope that helps anyone who lands here.
This worked for me
[System.Runtime.InteropServices.DllImport("user32", EntryPoint = "SetDisplayAutoRotationPreferences")]
private static extern UInt32 SetDisplayAutoRotationPreferences8(UInt32 orientation);
[System.Runtime.InteropServices.DllImport("kernel", EntryPoint = "SetDisplayAutoRotationPreferences")]
private static extern UInt32 SetDisplayAutoRotationPreferences7(UInt32 orientation);
public MyWindow()
{
InitializeComponent();
}
And on load of my main window :
SetDisplayAutoRotationPreferences8(2);//Lanscape

focus visual not showing when navigating focus programically

Whenever I try to move focus programmatically the focus visual (the dotted rectangle) does not display.
What can be done to force this visual to display?
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="OnLoaded">
<StackPanel>
<TextBlock x:Name="a" Focusable="True">A</TextBlock>
<TextBlock Focusable="True">B</TextBlock>
<Button Focusable="False" Click="OnClick">Move Focus</Button>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Keyboard.Focus(a);
}
private void OnClick(object sender, RoutedEventArgs e)
{
var request = new TraversalRequest(FocusNavigationDirection.Next);
var elementWithFocus = Keyboard.FocusedElement as UIElement;
if (elementWithFocus != null)
elementWithFocus.MoveFocus(request);
}
}
If you look (in reflector/ilspy) at the KeyboardNavigation's ShowFocusVisual you'll find that the framework will only show it if the last input was from the keyboard (or if an internal static property based on the KeyboardCues system parameter info is true). So I don't think there is a good way to do this short of using reflection to temporarily set that property or asynchronously focusing the element and forcing a keyboard action (maybe using the winforms SendKeys or keybd_event api) but I wouldn't recommend either.

How to Isolate Silverlight Memory Leaks

I have a memory leak in a silverlight app, I used this information to get started,
http://blogs.msdn.com/b/slperf/archive/2010/08/19/analyzing-silverlight-memory-usage-part-1-obtaining-measurements.aspx
Which was excellent. I have extracted some of my code to break down the issue. So the code looks like this, a child window,
<controls:ChildWindow x:Class="MemoryLeakTesting2.ConfirmDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls"
Width="375" >
<Grid Margin="2">
<telerik:RadButton Content="OK" Click="OnClick" Command="{Binding CancelActionCommand}" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
</Grid>
</controls:ChildWindow>
The code behind is this,
public partial class ConfirmDialog : ChildWindow
{
public ConfirmDialog()
{
InitializeComponent();
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
private void OnClick(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
}
I am calling this code from the button click event in my main silverlight page like this,
private void Button_Click(object sender, RoutedEventArgs e)
{
ConfirmDialog dialog = new ConfirmDialog();
dialog.Show();
}
This leaks memory every time I open the popup and close it. I use WinDbg and it actually shows that the ConfirmDialog instance is not freed after each time it is popped up and closed??
The Button.Command is notorious for leaking. My guess is that the value CancelActionCommand has a reference to a long lived object. The Button won't unhook from the ICommand.CanExecuteChanged event. You should consider using a Weak Event Pattern to limit your leakable surface area.
Here is a better explanation and example code to fix the problem.
Could it be:
On every click event you are creating ConfirmDialog object, which might hang around after it is no longer being used. Can you create that as a class variable and only have one reference and use that instead when you need to show the ChildWindow

Set the focus on a textbox in xaml wpf

Despite some posts on this forum and others i cannot find something that tells me how to set the focus on a TextBox.
I have a userControl with many labels and textBoxes. When the form is loaded I want the a particular textBox to have the focus.
I have set the tabIndex but that didn't seem to work.
Any suggestions?
You can use the FocusManager.FocusedElement attached property for this purpose. Here's a piece of code that set the focus to TxtB by default.
<StackPanel Orientation="Vertical" FocusManager.FocusedElement="{Binding ElementName=TxtB}">
<TextBox x:Name="TxtA" Text="A" />
<TextBox x:Name="TxtB" Text="B" />
</StackPanel>
You can also use TxtB.Focus() in your code-behind if you don't want to do this in XAML.
You can apply this property directly on the TextBox :
<TextBox Text="{Binding MyText}" FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>
I am new to using WPF and reading through the above examples I had a similar experience trying set the focus to a textbox using the xaml code examples given, i.e. all the examples above didn't work.
What I found was I had to place the FocusManager.FocusElement in the page element. I assume this would probably work as well if you used a Window as the parent element. Anyway, here is the code that worked for me.
<Page x:Class="NameOfYourClass"
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"
mc:Ignorable="d"
Title="Title"
Height="720"
Width="915"
Background="white"
Loaded="pgLoaded"
FocusManager.FocusedElement="{Binding ElementName=NameOfYourTextBox}">
<!-- Create child elements here. -->
</Page>
I have a TextBox inside a Grid inside a DataTemplate which I want to have keyboard focus when it becomes visible. I also found that
<DataTemplate x:Key="DistanceView" DataType="{x:Type vm:ROI}">
<Grid FocusManager.FocusedElement="{Binding ElementName=tbDistance}">
<TextBox x:Name="tbDistance" Grid.Column="1" Grid.Row="1" VerticalAlignment="Bottom"/>
</Grid>
</DataTemplate>
did not work for me.
However when I call Focus() in the parent ContentControl
private void ContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((sender as ContentControl).IsVisible)
{
(sender as ContentControl).Focus();
}
}
it starts to work and the caret is visible in the TextBox. I think the FocusScope has to be given focus for the FocusManager.FocusedElement property to have any effect.
Jerry
From experimenting around, the xaml solution
FocusManager.FocusedElement="{Binding ElementName=yourElement}"
seems to work best when you place it in the highest element in the window hierarchy (usually Window, or the Grid you place everything else in)
Usage:
local:FocusManager.FocusOnLoad="True"
public class FocusManager
{
public static readonly DependencyProperty FocusOnLoad = DependencyProperty.RegisterAttached(
"FocusOnLoad",
typeof(bool),
typeof(FocusManager),
new UIPropertyMetadata(false, new PropertyChangedCallback(OnValueChanged))
);
private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (!(sender is Control control))
return;
if ((bool) e.NewValue == false)
return;
control.Loaded += (s, e) => control.Focus();
}
public static bool GetFocusOnLoad(DependencyObject d) => (bool) d.GetValue(FocusOnLoad);
public static void SetFocusOnLoad(DependencyObject d, bool value) => d.SetValue(FocusOnLoad, value);
}
FocusManager was not in intellisense and this confused me a bit. I just typed the entire attribute and it worked.
FocusManager.FocusedElement="{Binding ElementName=MyTextBox}"
Microsoft Visual Studio Enterprise 2015 version 14.0.23107.0/C#/WPF
For completeness, there is also a way to handle this from code behind (e.g. in the case of controls that, for whatever reason, are created dynamically and don't exist in XAML). Attach a handler to the window's Loaded event and then use the ".Focus()" method of the control you want. Bare-bones example below.
public class MyWindow
{
private VisualCollection controls;
private TextBox textBox;
// constructor
public MyWindow()
{
controls = new VisualCollection(this);
textBox = new TextBox();
controls.Add(textBox);
Loaded += window_Loaded;
}
private void window_Loaded(object sender, RoutedEventArgs e)
{
textBox.Focus();
}
}
bind the element you want to point the focus in as
FocusManager.FocusedElement= "{Binding ElementName= Comobox1}"
in grid or groupbox etc
Further to my comment on Feb 04 '22, I solved it this way:
In the UserControl definitionin the XAML add a Loaded event handler. (pressing tab after Loaded= will automatically add an event handler to the code behind)
Then edit the event handler in the code behind:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
expressionTextBox.Focus();
}
I'm hoping that WPF is clever enough to handle th unhooking of the evnt at some point, allowing the class to be garbage collected and not give rise to memory leaks, but I don't know. I'd be interested in any comments on that.

Resources