trigger an event to hosting WPF application from webbrowser control - wpf

I have a WPF usercontrol that hosts an ASP.Net MVC Application using the webbrowser control.
I would like to notify the usercontrol when a certain action is performed on the WebApplication.
What are the possible ways to achieve this?

As #Szabolcs Dézsi mentioned in the comment if you have the access to Web Application you can use WebBrowser.ObjectForScripting to instance of an object and call its method from javascript. Here is a simple demo:
[ComVisible(true)] // Class must be ComVisible
public class Demo
{
public void SayHello(string name) => MessageBox.Show($"Hello {name} !!!");
}
Create an instance of this class an assign it to ObjectForScripting property of the WebBrowser control:
webBrowser.ObjectForScripting = new Demo();
and say this simple html page that we display in the WebBrowser control:
<html>
<head>
<title></title>
<script>
function sayhello()
{
var name = document.getElementById('name').value;
// the window.external is assigned an instance of
// class we created above.
// We can call C# instance method SayHello directly.
window.external.SayHello(name);
}
</script>
</head>
<body>
<form action="#" method="post">
<input id="name" type="text" name="name" value="" />
<input type="submit" name="submit" value="Say Hello" onclick="sayhello()" />
</form>
</body>
</html>
Now whenever you fill a name and click SayHello button it will display MessageBox as expected.
Also you have the property WebBrowser.Document which an instance of HtmlDocument that lives in Microsoft HTML Object Library (MSHTML) Com Library, make sure to reference it in your project.
The Document property allows you query the DOM object of the current page and through it you can manipulate your html page like in javascript via Method exposed by HtmlDocument Class like HtmlDocument.getElementById() and many others.
for example this code modify the value attribute of name input from above html page after page is loaded by WebBrowser control:
webBrowser.LoadCompleted += new LoadCompletedEventHandler((o, e) =>
{
if (webBrowser.Document is HTMLDocument DOM)
{
var namefield = DOM.getElementById("name");
namefield.setAttribute("value", "Enter your name!!!");
}
});
Hope this helps you to understand the power that WebBrowser control provides to manipulate loaded pages.

Related

Send PDF as attachment using React and .Net Core Web Api

I found alot of outdated options on the web so Just wandering what should be the best approach to convert DOM, as an PDF attachment and then send it via email.
I am using React as Front-end and .Net Core web Api as backend.
Thanks in Advance :)
Download jsPDF from Github Include these scripts below:
jspdf.js
jspdf.plugin.from_html.js
jspdf.plugin.split_text_to_size.js
jspdf.plugin.standard_fonts_metrics.js
If you want to ignore certain elements, you have to mark them with an
ID, which you can then ignore in a special element handler of jsPDF.
Therefore your HTML should look like this:
<!DOCTYPE html>
<html>
<body>
<p id="ignorePDF">don't print this to pdf</p>
<div>
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
Then you use the following JavaScript code to open the created PDF in
a PopUp:
var doc = new jsPDF();
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 180,'elementHandlers': elementHandler
});
doc.output("dataurlnewwindow");
One very important thing to add is that you lose all your style
information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3
etc., which was enough for my purposes. Additionally it will only
print text within text nodes, which means that it will not print the
values of textareas and the like. Example:
<body>
<ul>
<!-- This is printed as the element contains a textnode -->
<li>Print me!</li>
</ul>
<div>
<!-- This is not printed because jsPDF doesn't deal with the value attribute -->
<input type="textarea" value="Please print me, too!">
</div>
</body>
Attach the pdf and send emails with the help of this link

Bind click handler to dynamically created DOM elements

In my Ionic 2 app I have a template with this code:
<div class="body" [innerHTML]="ticket.Body | safeHtml"></div>
The body is HTML that is returned from a remote API. That HTML can contain images. I want to bind a "click" event handler on those images so that I can open them in an InAppBrowser when a user taps on them.
What would be the best way to do that?
Angular 4.1.3, Ionic 3.3.0
Solution 1
Try binding an event on to the parent to capture clicked target elements.
// HTML file
<div class="body" [innerHTML]="ticket.Body | safeHtml" (click)="bodyDivClick($event)" >
</div>
// TS file
bodyDivClick(event) {
// Check if the clicked target is an Image element.
// You can also check by css class name for specific image elements.
if (event.target && event.target.tagName === 'IMG') {
let imageElem = event.target;
console.log('Image clicked');
}
}
Solution 2
You can also try using ngFor to loop your results (images) into view and bind an event on the image itself.
Assuming that ticket is a JSON parsed object retrieved from the remote API.
<div class="body">
<div *ngFor="let imageUrl of ticket.images; let i = index;" class="image-container" >
<img src="{{imageUrl}}" class="image-style" (click)="imageClick()" />
</div>
</div>
Most probably the first solution might work for you if you are not able to change the response of the Remote API from html to JSON/objects (if it's not implemented by you).

Get the full file path in angular js mvc application

I am working on Angular js MVC application. I need a local file path which user selects from his/her local file system.
I know I can't get full file path in Javascript so I tried to get this using c#. So I added 1 chtml page with input box & controller to get the file
Here is chtml code
<div class="col-md-9">
#using (Html.BeginForm("GetFile", "File", FormMethod.Post, new { enctype = "multipart/form-data" })) {
<input type="file" name="file" />
<input type="submit" name="Submit" id="Submit" value="Upload" />
}
</div>
In controller I wrote
[HttpPost]
public ActionResult GetFile(HttpPostedFileBase file) {
if (file != null) {
string justFileName = Path.GetFullPath(file.FileName);
}
return justFileName;
}
}
Also I have added the route in routeprovider
.when('/File', {
templateUrl: 'File/Index'
})
I can easily access this page via URL. But now I need to call this page in an AngularJS modal popup or to show in a page itself on button click. I'm a bit newer to AngularJS. I tried with ng-view but it won't work. Please let me know If I am in a wrong direction? Is there any way to call chtml inside HTML? The question may be misleading but It is my final moto.
You need to add following line in your angular js controller when you want popup to be shown.
ngDialog.open({template: 'File/Index'});
Reference:
http://ngmodules.org/modules/ngDialog

What's the best way for an angular controller to alter an ancestor HTML element?

I have an Angular controller which lives in a portion of the page however that application needs to get access to an HTML element that lives above it.
The best way to imagine the problem is that you have an embedded video which wants to request to be made full view-port:
<html ng-app="videoApp">
<body>
<div>
Other stuff that doesn't relate to the video player...
</div>
<div ng-controller="videoCtrl">
... stuff relating to the video controller
</div>
</body>
</html>
The exact problem is that the videoCtrl needs to be able to add a class to the body class such that it can switch the page layout to being full-page and dominated by the video.
Desired outcome, status of video app adds a "full-page" class to body tag:
<body ng-class="video.fullPage ? 'full-page', : ''">
What's would be the correct way for the video to add a class to an ancestor tag?
Under normal circumstances where the element we want to manipulate lies inside the controller that's doing the manipulation we can bind elements to variables in the scope:
<body> <!-- the videoCtrl scope is not available to <body> -->
<div ng-controller="videoCtrl">
<div ng-class="video.fullPage ? 'fullPage' : ''"></div>
</div>
</body>
However the body tag is not contained within the scope of the video controller and so has no access to the variables in its scope so we can't bind to them.
We could always reach out directly and change the class on the body using dom manipulation but that's not very Angular. What is the correct pattern for the video controller to alter the class of the body tag?
To meet a very similar requirement, I used Angular events. From the controller, $broadcast an event on $rootScope. Then have some sort of screen layout controller handle the event and toggle the possible screen configurations.
So:
child controller:
$rootScope.$broadcast('layout-action', { configuration: 'video' });
layout controller:
$scope.$on('layout-action', function(event, args) {
if (args.configuration == 'video') {
$scope.showVideo = true;
}
});
html:
<body ng-class="{'full-page': showVideo}">
*Note: this does slightly tie the child functionality to another part of the layout. However, perhaps try to generalize the video layout. For example, maybe you want a full screen mode instead.
If ng-app="videoApp" is the only parent, you could also do something on the button that would trigger the full-page class like this:
<body ng-class="{'full-page': showVideo}">
<div ng-controller="videoCtrl">
<button ng-click="$parent.showVideo = !$parent.showVideo">I'm in the video controller!</button>
</div>
</body>
In this case i'm just toggling showVideo to true or false. But like Davin said, this may not be as nice because it depends more on where it sits in the app.
See this plunkr for an example http://plnkr.co/edit/UxtA0YvCUckofAflsy9G

Kendo UI with CakePHP 2.x

I am developing an appliction in CakePHP 2.x. and want to use Kendo UI. How can I do that and use it in my app? Can anyone tell me if it is possible and if so how?
My Controller:
class ClientDetailsController extends AppController {
var $name = "ClientDetails";
public $helpers = array('js');
public $components = array('RequestHandler');
function index(){
$this->loadModel('User');
$userdata = $this->User->find('all');
$this->set('user',$userdata);
}
}
My View:
<h1> User in Index Pages of the Client Details .... </h1>
<?php
//pr($user);
echo $this->Html->link('Personal Detail',array('controller'=>'ClientDetails','action'=>'add'));
?>
<div id="calendar" ></div>
<div id="info" > </div>
<?php
echo $this->Html->link('Room Details ',array('controller'=>'RoomDetails','action'=>'index'));
?>
I am not familiar with Kendo, however, I have used Knockout.js extensively with CakePHP. If you've used jQuery with CakePHP, the implementation with Kendo should be no different. I took a quick look and they appear to be similar in implementation, so this is what I would do.
Here in the Kendo documentation it says to simply link the necessary files. I don't see how this is any different than jQuery. Once the files are loaded you should be able to use them.
For example, use the following code at the top of your view (but obviously with your paths)
<!-- Common Kendo UI Web CSS -->
<link href="styles/kendo.common.min.css" rel="stylesheet" />
<!-- Default Kendo UI Web theme CSS -->
<link href="styles/kendo.default.min.css" rel="stylesheet" />
<!-- jQuery JavaScript -->
<script src="js/jquery.min.js"></script>
<!-- Kendo UI Web combined JavaScript -->
<script src="js/kendo.web.min.js"></script>
//rest of your code here
Now you can use Kendo however you like. In their documentation they list the datepicker, such as
<input id="datepicker" />
<script>
$(function() {
// Initialize the Kendo DatePicker by calling the kendoDatePicker jQuery plugin
$("#datepicker").kendoDatePicker();
});
</script>
So, if you had a date input, just put put the ID of that input where "#datepicker" is listed in the example above.

Resources