Integrate VLC player in C# (WPF) project using Vlc.DotNet - wpf

I want to integrate to my project a VLC player to display video cameras streams. For that, I try to use Vlc.DotNet (2.1.126 version) in my WPF project.
My tests are done in the following XAML file (I'm a bit a beginner at XAML/WPF):
<UserControl x:Class="TVSCS_View.VideoDisplay.VideoPlayerControl"
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:ctrl="clr-namespace:TVSCS_View.VideoDisplay"
xmlns:wpf="clr-namespace:Vlc.DotNet.Wpf;assembly=Vlc.DotNet.Wpf"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
x:Name="controlVideoDisplay"
DataContext="{Binding ElementName=controlVideoDisplay}">
<Border BorderBrush="Black"
BorderThickness="1">
<Grid x:Name="videoDisplayLayoutRoot"
Margin="5,5,5,5">
<Image Source="{Binding ElementName=myVlcControl}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<ctrl:VideoCommandsControl x:Name="videoPlayerControl"
VerticalAlignment="Bottom"
Height="25"
Width="175"
Visibility="Visible"
Margin="10,0,10,20" />
<ctrl:VideoTimeLineControl x:Name="timeLineControl"
VerticalAlignment="Bottom"
Margin="0,0,0,0"/>
</Grid>
</Border>
</UserControl>
And the associated .cs file is:
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Vlc.DotNet.Wpf;
namespace TVSCS_View.VideoDisplay
{
/// <summary>
/// Logique d'interaction pour VideoPlayerControl.xaml
/// </summary>
public partial class VideoPlayerControl : UserControl
{
public VlcControl myVlcControl;
public VideoPlayerControl()
{
InitializeComponent();
MediaPlayer media = new MediaPlayer();
myVlcControl = new VlcControl();
var currentAssembly = Assembly.GetEntryAssembly();
var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
if (Environment.Is64BitOperatingSystem)
{
myVlcControl.MediaPlayer.VlcLibDirectory = new DirectoryInfo(System.IO.Path.Combine(currentDirectory, #"C:\Users\t0115019\Documents\Visual Studio 2015\Projects\tvscs_display\packages\VLC\"));
}
myVlcControl.MediaPlayer.EndInit();
myVlcControl.MediaPlayer.Play(new Uri("C:/Users/Documents/WP_20160908_11_16_53_Pro.mp4"));
}
}
}
Currently, I have an exception "FillNotFOundException" linked to "myVlcControl.MediaPlayer.EndInit()" line when I execute the application.
If I delete this line, nothing is displayed in the UserControl.
Nota:
I try to integrate the VlcControl using the following method:
<UserControl x:Class="TVSCS_View.VideoDisplay.VideoPlayerControl"
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:ctrl="clr-namespace:TVSCS_View.VideoDisplay"
xmlns:wpf="clr-namespace:Vlc.DotNet.Wpf;assembly=Vlc.DotNet.Wpf"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
x:Name="controlVideoDisplay"
DataContext="{Binding ElementName=controlVideoDisplay}">
<Border BorderBrush="Black"
BorderThickness="1">
<Grid x:Name="videoDisplayLayoutRoot"
Margin="5,5,5,5">
<wpf:VlcControl x:Name="myVlcControl" />
</Grid>
</Border>
</UserControl>
But in this case, i have the following messsage:
the value of type "VlcControl" cannot be added to a collection or dictionary of type 'UIElementCollection'.
Do you have any solution for my little problem?
Thanks

The WPF version of the VlcControl is just a WindowsFormsHost control hosting the Windows Forms version of the VlcControl. Judging by the error message (The value of type "VlcControl" cannot be added to a collection or dictionary of type 'UIElementCollection') you're simply missing a reference to the WindowsFormsIntegration assembly, in which the WindowsFormsHost is defined (it can be found under Assemblies → Framework in the reference manager).
Here's a fully working example of a WPF window hosting the VLC player. You need to install the Vlc.DotNet.Wpf NuGet package (and its dependencies) and reference the WindowsFormsIntegration assembly.
MainWindow.xaml
<Window x:Class="HelloVlc.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vlc="clr-namespace:Vlc.DotNet.Wpf;assembly=Vlc.DotNet.Wpf">
<vlc:VlcControl x:Name="vlcPlayer" />
</Window>
MainWindow.xaml.cs
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
vlcPlayer.MediaPlayer.VlcLibDirectory =
//replace this path with an appropriate one
new DirectoryInfo(#"c:\Program Files (x86)\VideoLAN\VLC\");
vlcPlayer.MediaPlayer.EndInit();
vlcPlayer.MediaPlayer.Play(new Uri("http://download.blender.org/peach/" +
"bigbuckbunny_movies/big_buck_bunny_480p_surround-fix.avi"));
}
}

Related

MSVS - WPF - How do I make ProjectName.csproj build App.xaml and App.xaml.cs last?

My WPF project has App.xaml require other pieces of project code to be built before it gets built. Despite App.xaml's dependency on those classes and xaml files, Visual Studio wants to build it first before anything else can get built.
For further information, here's the dependencies that are not getting addressed when I build from scratch.
XAML namespaces:
xmlns:views="clr-namespace:ProjectName.Views"
xmlns:viewmodels="clr-namespace:ProjectName.ViewModels"
XAML namespace implementations:
<DataTemplate DataType="{x:Type viewmodels:HomeViewModel}">
<views:HomeView/>
</DataTemplate>
HomeViewModel is a class in ...ViewModels.
HomeView is a class and XAML file in ...Views.
I know that the .csproj build order is the main problem, because I built the solution omitting the datatemplates and got no errors, and when I built after putting them back in I am still fine.
But when I cleaned the solution and rebuilt, I get errors up the wazoo!
I am making an MVVM application and I absolutely need App.xaml to be built last, as otherwise it would be difficult to make further iterations (as in, more Views / ViewModels) to this project.
How do I alter the .csproj files so that this happens?
I'm using MS Visual Studio Community 2019.
Also, I tried looking through build targets and overriding them but I can't figure out how to make it so that certain pieces of source code get built last.
Additional context:
App.xaml
<Application x:Class="ProjectName.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProjectName;assembly=ProjectName"
xmlns:views="clr-namespace:ProjectName.Views"
xmlns:viewmodels="clr-namespace:ProjectName.ViewModels"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!--
<DataTemplate DataType="{x:Type viewmodels:MainViewModel}">
<views:MainView/>
</DataTemplate>
-->
<DataTemplate DataType="{x:Type viewmodels:NGViewModel}">
<views:NGView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:HomeViewModel}">
<views:HomeView/>
</DataTemplate>
<!---->
</Application.Resources>
</Application>
HomeView.xaml.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ProjectName.Views
{
/// <summary>
/// Interaction logic for HomeView.xaml
/// </summary>
public partial class HomeView : UserControl
{
public HomeView()
{
InitializeComponent();
}
}
}
HomeView.xaml
<UserControl x:Class="ProjectName.Views.HomeView"
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:ProjectName.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="Black">
</Grid>
</UserControl>
HomeViewModel.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace ProjectName.ViewModels
{
public class HomeViewModel : BaseViewModel
{
}
}
BaseViewModel.cs (bonus - parent class of HomeViewModel)
using System;
using System.Collections.Generic;
using System.Text;
namespace Prototype7022.ViewModels
{
public class BaseViewModel
{
}
}

How can I bind the value cross the window?

Here is the 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="450" Width="800">
<Grid>
<TextBox Text="{Binding CB+Width,RelativeSource={RelativeSource AncestorType={x:Type Window}},Mode=TwoWay}"></TextBox>
</Grid>
</Window>
And here is code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TB = new TextBox();
TB.Width = 200;
}
public ComboBox CB
{
get { return (ComboBox)GetValue(CBProperty); }
set { SetValue(CBProperty, value); }
}
// Using a DependencyProperty as the backing store for CB. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CBProperty =
DependencyProperty.Register("CB", typeof(ComboBox), typeof(MainWindow), null);
}
}
In fact, the DependencyProperty is a custom control, but I replace it as a ComboBox for easy to explain my problem to you.
The custom control is not in the same window and I want to bind its value such as Width to the TextBox.
The custom control is in a different window. That means there are two windows, window 1 and window 2. The custom control is in window 1 and the textbox is in window 2. I do this because one is the main window and the other is the setting window. Whenever the setting window changes the setting, you can see it in the main window at once. So I use a DependencyProperty to store the custom control which in a different window and wanna bind it to the textbox.
Now how can I do it? Would you please help me? Thank you.
It LOOKs like you want your textbox to show the width property of the Window? (or some other control in the future and just testing). If you apply an x:Name value to a control, you can reference that control directly in the XMAL and then properties directly on that. No need for any custom other control with your own dependency property... something like.
<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="450" Width="800"
x:Name="myOuterWindowControl" >
<Grid>
<TextBox Text="{Binding ElementName=myOuterWindowControl, Path=Width, Mode=TwoWay,
UpdateSourceTrigger=LostFocus}" Height="30" Width="70"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBox Height="30" Width="70"
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,50,0,0"/>
</Grid>
</Window>
Now I actually added an extra textbox control so there is more than one control in the XAML to allow focus to change. Reason. I set the textbox to allow mode as Two-Way binding. The window will push to the textbox, but you can also type in a value to the textbox and when the LOST FOCUS happens, it pushes the value back to the window and you can dynamically change the width (or other property height, coloring, whatever).
Is this more in line with what you were trying to get at?

Unable to fire InvokeCommandAction

On click of a textblock, I want to lift its contents in my view model and if accurate, navigate to another page. Unfortunately for me, the click event never triggers its bound command. Below is my code
In the xaml, I have this markup
<UserControl x:Class="SchoolPrism.Login.Views.Login"
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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SchoolPrism.Login.Views"
xmlns:prism="http://prismlibrary.com/"
xmlns:constants="clr-namespace:Infrastructure.Constants;assembly=SchoolPrismInfrastructure"
xmlns:login="clr-namespace:SchoolPrism.Login.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<!-- when we have a view model, bind to that instead-->
<Grid DataContext="{Binding login:LoginViewModel}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="5*"/>
</Grid.RowDefinitions>
<TextBlock DataContext="{Binding}" Text="{Binding FormResults}"></TextBlock>
<TextBlock Text="hi, can you see me?" x:Name="SchoolCode" Grid.RowSpan="2" Margin="0,50,0,0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseDown">
<!--tried replacing interactivity with prism here but it had no effect -->
<i:InvokeCommandAction Command="{Binding submitForm}" CommandParameter="{Binding Text, ElementName=SchoolCode}" ></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</Grid>
</UserControl>
Then, in the view model, I have this
using Prism.Commands;
using Prism.Modularity;
using SchoolPrism.Modules.Login;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace SchoolPrism.Login.ViewModel
{
class LoginViewModel
{
ICommand submitForm
{
get { return new DelegateCommand<string>(SubmitForm); }
}
public void SubmitForm(string code)
{
// interact with model over given code
// if auth, get module instance and invoke the following
new LoginModule().proceedToNext("AllTopics");
}
}
}
Finally, in the module proper, I have
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;
using Prism.Commands;
using Prism.Modularity;
using Prism.Mvvm;
using Prism.Regions;
using SchoolPrism.Login.Views;
using System;
using System.Windows;
using System.Windows.Input;
namespace SchoolPrism.Modules.Login
{
[Module(ModuleName = "LoginModule")]
class LoginModule : BindableBase, IModule
{
IRegionManager _regionMan;
// this method is called on our behalf by prism
public void Initialize ()
{
_regionMan = ServiceLocator.Current.GetInstance<iregionmanager>();
}
public void proceedToNext (string target)
{
_regionMan.RequestNavigate("LoginForm", new Uri(target, UriKind.Relative)/*, (NavigationResult result) => { return code.Length > 0; }*/);
}
}
}
The fault is from this line
<Grid DataContext="{Binding login:LoginViewModel}">
This is acceptable for binding to properties and not to the contexts themselves. Unfortunately, the compiler doesn't complain. The appropriate syntax for binding to a context is
<Control.DataContext>
<namespace:ContextObj>
</Control.DataContext>
which in this case would be:
<Grid.DataContext>
<login:LoginViewModel></login:LoginViewModel>
</Grid.DataContext>

repeat button wpf not firing off click event

Hello community I have the following xaml.
<UserControl x:Class="Sample.SampleController"
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"
d:DesignHeight="410" d:DesignWidth="324">
<UserControl.Resources>
<Style x:Key="buttonON" TargetType="RepeatButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Grid Width="80"
Height="80">
<Image Source="/Sample;component/icons/altitude_up_yellow.png"
Stretch="Fill" RenderOptions.BitmapScalingMode="Fant"/>
<ContentPresenter HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Name="DriveGrid" Background="#C9000000" Width="324" Height="410">
<RepeatButton HorizontalAlignment="Left" x:Name="button1" VerticalAlignment="Top" IsEnabled="True" Style="{StaticResource buttonON}" Margin="232,297,0,0" Delay="100" Interval="200" Width="80" Height="80"/>
</Grid>
</UserControl>
And the following Code Behind
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Windows.Controls.Primitives;
namespace Sample {
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class SampleController : UserControl {
public SampleController() {
InitializeComponent();
button1.Click += new RoutedEventHandler(UpBtn_Click);
}
void UpBtn_Click(object sender, RoutedEventArgs e) {
Console.WriteLine("Click");
}
}
}
My question, why doesn't the repeat button fire off continously when I press and hold?
Thank you for your help.
To sum up comments. Even though I am not able to reproduce the problem stated in the question, as the code above works fine for me, I have found very similar issue in RepeatButton fires event only once! article. There is no definite answer what's causing the issue but it may give some clues to what to try

How do I get DependencyProperty to work in Silverlight?

I'm trying to bind using a DependencyProperty, but I can't even get the DependencyProperty to work let alone try to bind to it.
I'm following a silverlight guide and up to this point I'm supposed to be able to set the property using XAML. Here is the code I have so far:
MainPage.xaml:
<UserControl
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:UserControlSample" x:Class="UserControlSample.MainPage"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<local:InfoRectangle Margin="32,36,0,0" HorizontalAlignment="Left" Height="70" VerticalAlignment="Top" Width="122" InfoText="New Text"/>
<local:InfoRectangle Margin="105,139,188,97" InfoText="some text" />
</Grid>
InfoRectangle.xaml:
<UserControl
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
mc:Ignorable="d"
x:Class="UserControlSample.InfoRectangle"
d:DesignWidth="122" d:DesignHeight="70">
<Grid x:Name="LayoutRoot">
<Rectangle Fill="#FFABABE9" Stroke="Black" RadiusY="4" RadiusX="4"/>
<TextBlock Name="InfoLabel" Text="Text block" Margin="5" />
</Grid>
InfoRectangle.xaml.cs:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace UserControlSample
{
public partial class InfoRectangle : UserControl
{
public InfoRectangle()
{
// Required to initialize variables
InitializeComponent();
}
public string InfoText
{
get { return (string)GetValue(InfoTextProperty); }
set { SetValue(InfoTextProperty, value); }
}
public static readonly DependencyProperty InfoTextProperty =
DependencyProperty.Register(
"InfoText",
typeof(string),
typeof(InfoRectangle),
new PropertyMetadata("something", InfoTextChanged));
private static void InfoTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
}
}
When I run the solution the two rectangles show up but they display just "Text block" which is neither the default set or the value set in the MainPage XAML for the user controls.
My answer in here details a nice compact example of a dependency property updating a given property on a view model. The property on your view model would be bound to your text block so once change notification fires, your text block should update.
Here is the solution;
It seems the callback method has to be completed.
private static void InfoTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((InfoRectangle)d).InfoLabel.Text = e.NewValue.ToString();
}

Resources