I'm trying to simulate a user typing a value into an "input" field on a website, and I'm getting very strange exception when trying to run InvokeMember. I tested several approaches and I found that most online documentation is outdated and simply doesn't work. Unfortunately the mostly suggested solution to my problem seems to throw a very strange exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
''System.MarshalByRefObject.InvokeMember(string,
System.Reflection.BindingFlags, System.Reflection.Binder, object[],
System.Reflection.ParameterModifier[],
System.Globalization.CultureInfo, string[])' is inaccessible due to
its protection level'
This is an example code that recreates the problem:
MainWindow.xaml
<Window x:Class="Example.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:Example"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel>
<WebBrowser x:Name="ie"/>
</DockPanel>
</Window>
MainWindow.xaml.cs
using mshtml;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Navigation;
namespace Example
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ie.LoadCompleted += (o, e) =>
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (wo, we) => { Thread.Sleep(5000); };
worker.RunWorkerCompleted += (wo, we) => { DelayedLoadCompleted(); };
worker.RunWorkerAsync();
};
ie.Navigate(#"https://google.com");
}
private void DelayedLoadCompleted()
{
HTMLDocument doc = (ie.Document as HTMLDocument);
dynamic input = doc.getElementById("lst-ib");
input.InvokeMember("onkeypress", new { Key = 65 }); //throws that excetpion
input.InvokeMember("click"); //throws that excetpion
input.click(); //works fine
}
}
}
The line input.InvokeMember("click"); throws that exception, but input.click(); works just fine.
What is the cause of that exception?
Related
In the file MainWindow.xaml.cs in the method TakeScreenShot i'm getting exception on the
line :
var executedScript = WebView.EvaluateScriptAsync(jsString).Result.Result;
System.Exception
HResult=0x80131500
Message=Unable to execute javascript at this time, scripts can only be executed within a V8Context. Use the IWebBrowser.CanExecuteJavascriptInMainFrame property to guard against this exception. See https://github.com/cefsharp/CefSharp/wiki/General-Usage#when-can-i-start-executing-javascript for more details on when you can execute javascript. For frames that do not contain Javascript then no V8Context will be created. Executing a script once the frame has loaded it's possible to create a V8Context. You can use browser.GetMainFrame().ExecuteJavaScriptAsync(script) or browser.GetMainFrame().EvaluateScriptAsync to bypass these checks (advanced users only).
Source=CefSharp
StackTrace:
at CefSharp.WebBrowserExtensions.ThrowExceptionIfCanExecuteJavascriptInMainFrameFalse()
at CefSharp.WebBrowserExtensions.EvaluateScriptAsync(IChromiumWebBrowserBase browser, String script, Nullable`1 timeout, Boolean useImmediatelyInvokedFuncExpression)
at Web_Browser_WPF.MainWindow.TakeScreenShot(String siteUrl) in D:\Csharp Projects\Web Browser WPF\MainWindow.xaml.cs:line 47
at Web_Browser_WPF.MainWindow.ChromiumWebBrowser_LoadingStateChanged(Object sender, LoadingStateChangedEventArgs e) in D:\Csharp Projects\Web Browser WPF\MainWindow.xaml.cs:line 64
at CefSharp.Wpf.ChromiumWebBrowser.CefSharp.Internals.IWebBrowserInternal.SetLoadingStateChange(LoadingStateChangedEventArgs args)
at CefSharp.Internals.ClientAdapter.OnLoadingStateChange(ClientAdapter* , scoped_refptr* browser, Boolean isLoading, Boolean canGoBack, Boolean canGoForward)
and then if i mark as comment not to use the part of the jString and executedScript and not assigning to the height then i'm getting null exception on the line :
bitmap.Save(#"d:\Test.jpg");
because WebView is null.
so i'm stuck here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
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 CefSharp;
using CefSharp.OffScreen;
namespace Web_Browser_WPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
WindowStartupLocation =
System.Windows.WindowStartupLocation.CenterScreen;
}
private void TakeScreenShot(string siteUrl)
{
CefSharp.OffScreen.ChromiumWebBrowser WebView = new CefSharp.OffScreen.ChromiumWebBrowser(siteUrl);
int width = 1280;
int height = 1480;
string jsString = "Math.max(document.body.scrollHeight, " +
"document.documentElement.scrollHeight, document.body.offsetHeight, " +
"document.documentElement.offsetHeight, document.body.clientHeight, " +
"document.documentElement.clientHeight);";
var executedScript = WebView.EvaluateScriptAsync(jsString).Result.Result;
height = Convert.ToInt32(executedScript);
WebView.Size = new System.Drawing.Size(width, height); //size;
Thread.Sleep(500);
// Wait for the screenshot to be taken.
var bitmap = WebView.ScreenshotOrNull();
bitmap.Save(#"d:\Test.jpg");
bitmap.Dispose();
}
private void ChromiumWebBrowser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
{
if(!e.IsLoading)
{
TakeScreenShot("https://ims.gov.il/he/RadarSatellite");
}
}
}
}
The xaml code
<Window
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:cef="clr-namespace:Web_Browser_WPF"
xmlns:Wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf" x:Class="Web_Browser_WPF.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="720" Width="1024">
<Grid>
<Wpf:ChromiumWebBrowser HorizontalAlignment="Left" Margin="363,181,0,0" VerticalAlignment="Top"/>
<Wpf:ChromiumWebBrowser x:Name="chromiumBrowser1"/>
<Wpf:ChromiumWebBrowser Address="https://ims.gov.il/he/RadarSatellite" LoadingStateChanged="ChromiumWebBrowser_LoadingStateChanged" />
</Grid>
</Window>
I have excel where in Sheet 1 i have 2 tables ,i want to read data by infragistics WPF and bind in UI below is the structure of data in excel , i am new to WPF can anyone help
One of the methods to read the Excel file is using the XamSpreadsheet control that allows visualizing and editing of spreadsheet data.
There is the code example.
using Infragistics.Documents.Excel;
using System;
using System.IO;
using System.Windows;
using System.Windows.Resources;
namespace ReadExcelFile
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LoadFile();
}
private void LoadFile()
{
// For this example the excel document is located in resources
var fileName = "/ReadExcelFile;component/Resources/Book1.xlsx";
Stream stream = GetFileAsStream(fileName);
if (Workbook.Load(stream) is Workbook wb)
{
this.xamSpreadsheet1.Workbook = wb;
this.Title = "Book1.xlsx";
}
}
public static Stream GetFileAsStream(string fullName)
{
StreamResourceInfo sri = Application.GetResourceStream(new Uri(fullName, UriKind.Relative));
return sri.Stream;
}
}
}
The XAML:
<Window x:Class="ReadExcelFile.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:ig="http://schemas.infragistics.com/xaml"
mc:Ignorable="d"
Height="450" Width="800">
<Grid>
<ig:XamSpreadsheet x:Name="xamSpreadsheet1" />
</Grid>
</Window>
The application will looks like on the screenshot:
It is necessary add references to the following assemblies:
InfragisticsWPF4.Controls.Grids.XamSpreadsheet
InfragisticsWPF4.Documents.Excel
For additional information see: XamSpreadsheet
The following code sample from Microsoft is causing an external exception when used against UWP version 1903 Build 18362 and Nuget package Win2d 1.25.0
The memory access violation happens on mediaPlayer.CopyFrameToVideoSurface(inputBitmap);
And it happens no matter what video the MediaPlayer is trying to play.
The example_video.mkv file in the Assets folder is the file sample_640x360.mkv from this video sample page. Ultimately I tried multiple file formats both local and streaming, and it didn't change the exception being thrown.
Also I tried locking the CanvasDevice as is seen by the CanvasLock which is commented out, but that also changed nothing.
The Fatal Exception Thrown:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
MainPage.xaml.cs:
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using Windows.Graphics.Display;
using Windows.Graphics.Imaging;
using Windows.Media.Core;
using Windows.Media.Playback;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace MediaPlayerTest
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
MediaPlayer mediaPlayer;
SoftwareBitmap frameServerDest;
CanvasImageSource canvasImageSource;
public MainPage()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer.VideoFrameAvailable += mediaPlayer_VideoFrameAvailable;
mediaPlayer.IsVideoFrameServerEnabled = true;
mediaPlayer.Play();
}
// FROM: https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/play-audio-and-video-with-mediaplayer#use-mediaplayer-in-frame-server-mode
private async void mediaPlayer_VideoFrameAvailable(MediaPlayer sender, object args)
{
CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (frameServerDest == null)
{
// FrameServerImage in this example is a XAML image control
frameServerDest = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)FrameServerImage.Width, (int)FrameServerImage.Height, BitmapAlphaMode.Ignore);
}
if (canvasImageSource == null)
{
canvasImageSource = new CanvasImageSource(canvasDevice, (int)FrameServerImage.Width, (int)FrameServerImage.Height, DisplayInformation.GetForCurrentView().LogicalDpi);//96);
FrameServerImage.Source = canvasImageSource;
}
using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, frameServerDest))
using (CanvasDrawingSession ds = canvasImageSource.CreateDrawingSession(Windows.UI.Colors.Black))
{
// CanvasLock lk = canvasDevice.Lock();
mediaPlayer.CopyFrameToVideoSurface(inputBitmap);
// lk.Dispose();
var gaussianBlurEffect = new GaussianBlurEffect
{
Source = inputBitmap,
BlurAmount = 5f,
Optimization = EffectOptimization.Speed
};
ds.DrawImage(gaussianBlurEffect);
}
});
}
}
}
MainPage.xaml:
<Page
x:Class="MediaPlayerTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MediaPlayerTest"
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>
<Button Content="Play Video" FontSize="40" HorizontalAlignment="Left" Height="78" Margin="156,110,0,0" VerticalAlignment="Top" Width="288" Click="Button_Click"/>
<Image x:Name="FrameServerImage" Height="360" Width="640" Margin="156,246,704,0" VerticalAlignment="Top"/>
</Grid>
</Page>
I need to expand an existing Run to include some new text (with different formatting) without adding an additional paragraph. Is this possible?
When I inspect the properties of the FirstBlock on the Document, I do not see any property which allow me to drill down into the paragraph so that I can add a Run to it.
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 WpfApp3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.flowdoc.Document = new FlowDocument();
Run r = new Run("Hello ");
r.Background = new SolidColorBrush(Colors.Yellow);
r.FontSize = 14;
Paragraph p = new Paragraph(r);
flowdoc.Document.Blocks.Add(p);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Run r = new Run("World");
r.Background = new SolidColorBrush(Colors.LightCyan);
//Append run to existing run
//
}
}
}
<Window x:Class="WpfApp3.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:WpfApp3"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<FlowDocumentReader Grid.Column="0" x:Name="flowdoc"></FlowDocumentReader>
<Button Grid.Column="1" Content="append" Click="Button_Click"></Button>
</Grid>
</Window>
To get your Paragraph you may iterate the Blocks property of the document.
You can then easily add a new Run to the Block's Inlines collection.
private void Button_Click(object sender, RoutedEventArgs e)
{
Run r = new Run("World");
r.Background = new SolidColorBrush(Colors.LightCyan);
//Append run to existing run
var p = flowdoc.Document.Blocks.OfType<Paragraph>().First();
p.Inlines.Add(r);
}
I have an MVVMLight multi-page application which has two pages, I can navigate from one page to the other by clicking the respective buttons.
In the second page, I have a loader animation that is triggered every time something is typed in a textBox field. Everything is working fine; from the first page I can go to the second page then you type something in the textBox and the animation starts. The problem is that if I go to the second page, then I go back to the first page and then I go to the second page again and type something in the textBox I get an error that says that the name of the loader doesn't exist, the funny thing is that I don't get this error until I leave the page and come back.
Any idea why the animation stops working after leaving the page and coming back?
EDIT: Here is the link to a complete project.
https://www.dropbox.com/sh/yf87shw5rzxtxen/AAClTesIGpLKl6IzV-6pjfEfa?dl=0
To replicate error do the following...
Download and open application.
Go to page 2.
Type something in the textBox (animation should start).
Go back to page 1, do nothing.
Go to page 2 again and try typing something in the textBox (you should see the error here).
Error:
Additional information: 'rectangleLoader' name cannot be found in the name scope of 'TwoViews.Views.SecondView'.
XAML
<UserControl x:Class="TwoViews.Views.SecondView"
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"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<Rectangle x:Name="rectangleLoader" Fill="#FFB2B2FF" HorizontalAlignment="Left" Height="19" Margin="26,89,0,0" VerticalAlignment="Top" Width="248"/>
<TextBox x:Name="textBoxFileName"
HorizontalAlignment="Left"
Height="35" Width="180"
Margin="26,125,0,0"
VerticalAlignment="Top"
Text="{Binding InputFileNameChanged, UpdateSourceTrigger=PropertyChanged}" FontSize="18"/>
</Grid>
</UserControl>
SecondView.xaml.cs
namespace TwoViews.Views
{
public partial class SecondView : UserControl
{
private Storyboard loaderStoryboard;
public SecondView()
{
InitializeComponent();
Messenger.Default.Register<MessageSearchStatus>(this, messageSearchStatus => ReceivedSearchStatus(messageSearchStatus));
/// Animation for loader
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 100;
myDoubleAnimation.To = 0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(.1));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
loaderStoryboard = new Storyboard();
loaderStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, rectangleLoader.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty));
}
private void ReceivedSearchStatus(MessageSearchStatus message)
{
loaderStoryboard.Begin(this, true);
}
/// I manually stop the animation before going to other screens
private void stopAnimation_Click(object sender, System.Windows.RoutedEventArgs e)
{
loaderStoryboard.Stop(this);
}
}
}
ViewModel
namespace TwoViews.ViewModels
{
public class SecondViewModel : ViewModelBase
{
private string _inputFileName;
public string InputFileNameChanged
{
get { return _inputFileName; }
set {
// send message to start animation everytime the textBox changes
Messenger.Default.Send<MessageSearchStatus>(new MessageSearchStatus { isSearchingFile = true });
}
}
}
}
Please note that in my code I'm not showing the code that stops the animation.
Again, the animation works fine until the user leaves the page where the animation is and comes back.
Thanks!
FYI - The issue appeared to be the Storyboard I was using with the animation. Removed the Storyboard and everything work fine.
SecondView.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System;
using System.Windows.Input;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Threading;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Collections.Specialized;
using System.Linq;
using System.Windows.Shapes;
using TwoViews.Models;
using System.Windows.Media;
namespace TwoViews.Views
{
public partial class SecondView : UserControl
{
private DoubleAnimation myDoubleAnimation;
public SecondView()
{
InitializeComponent();
Messenger.Default.Register<MessageSearchStatus>(this, messageSearchStatus => ReceivedSearchStatus(messageSearchStatus));
/// Animation for loader
myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 100;
myDoubleAnimation.To = 0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(.1));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
}
private void ReceivedSearchStatus(MessageSearchStatus message)
{
rectangleLoader.BeginAnimation(Rectangle.WidthProperty, myDoubleAnimation);
}
private void stopAnimation_Click(object sender, System.Windows.RoutedEventArgs e)
{
rectangleLoader.BeginAnimation(Rectangle.WidthProperty, null);
}
}
}