Where is ExecWB? - wpf

If I use WPF syntax:
<WebBrowser Grid.Row="1" Grid.Column="1" x:Name="htmlView"></WebBrowser>
Or if I add a WindowsFormsHost:
<WindowsFormsHost x:Name="formsHost" Grid.Row="1" Grid.Column="1">
</WindowsFormsHost>
And in the CS file:
public partial class MainWindow : Window
{
System.Windows.Forms.WebBrowser htmlView= new System.Windows.Forms.WebBrowser();
public MainWindow()
{
InitializeComponent();
formsHost.Child = htmlView;
htmlView.Navigate("d:\\test.xml");
}
private void menuFilePageSetup_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Do do");
}
}
Either way, the ExecWB method is not exposed. So I can't port this code over from my MFC C++ CHtmlView derived class:
ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
Am I missing something? At this point in time I can't implement my print preview / page setup / zoom functionality because I can't use ExecWB.
I have tried deriving my own class from the Winforms browser but it is still not listed.
Thank you.
I don't understand why in this question:
How do I programmatically change printer settings with the WebBrowser control?
It refers to ShowPrintDialog but even that is not listed.
Partial success! I don't know why, but now, when I use the hosted Winforms version, I can atleast see some of the methods:
public partial class MainWindow : Window
{
System.Windows.Forms.WebBrowser htmlView= new System.Windows.Forms.WebBrowser();
public MainWindow()
{
InitializeComponent();
formsHost.Child = htmlView;
htmlView.Navigate("d:\\test.xml");
}
private void menuFilePageSetup_Click(object sender, RoutedEventArgs e)
{
htmlView.ShowPageSetupDialog();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
htmlView.ShowPrintPreviewDialog();
}
}
But ExecWb is still missing for managing things like zooming. I found this:
How do I print from the wpf WebBrowser available in .net 3.5 SP1?
One of the answers:
mshtml.IHTMLDocument2 doc = webBrowser.Document as mshtml.IHTMLDocument2;
doc.execCommand("Print", true, null);
But even if I add a reference to the mshtml library the compiler will not let me convert from HtmlDocument to IHtmlDocument2. Eventually I got this:
Clearing the selection in a webbrowser control
So now I know how to select all and copy to clipboard again (as long as I use the Winforms edition). However, having looked here:
https://msdn.microsoft.com/en-us/library/ms533049(v=vs.85).aspx
There seems to be no match for Optical Zoom:
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &vZoom, NULL);

The basic answer for calling ExecWb is to do this:
Use the WinForms WebBrowser control
Then something like htmlView.Document.ExecCommand
Pass in commands like:
SelectAll
Copy
for clipboard items.
There are native methods for displaying the print dialogues etc..
Only thing that does not seem to be supported is:
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &vZoom, NULL);

Related

XAML detect when users's mouse leaves Silverlight window

Does XAML provide a way to detect if the user's mouse cursor has left the Silverlight window? If so, how would I go about doing this?
Thanks for your help.
Yes there is.
Assuming the the MainPage is your RootVisual and you've added a reference for System.Windows.Browser assembly then the following code should work.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
//objSilverlight is the <object> tag id
var element = HtmlPage.Document.GetElementById("objSilverlight");
element.AttachEvent("onmouseout", new EventHandler(HandleMouseOut));
}
public void HandleMouseOut(object sender, EventArgs args)
{
//handle your event here
}
}
Basically the .Net event handler is being attached to the onmouseout DOM event in the Html object element that contains the silverlight plugin.

undo/redo command stack for InkCanvas

I am creating paint like application using InkCanvas , I am willing to implement Undo
and Redo functionality in my application .
Which is the best way to implement Undo / Redo for InkCanvas ??
I've implemented undo / redo for a WPF application and ended up publishing my undo / redo code to http://muf.codeplex.com/. You can also get it via NuGet. Just look for "MUF" or "Monitored Undo Framework". It includes support for Silverlight 4.0, as well as .NET 3.5, 4.0, and WP7.
In my WPF app, we also had an InkCanvas that supported Undo / Redo. In my case, the strokes for the InkCanvas were saved to a database with the rest of the data. I hooked the various events on InkCanvas to detect when the strokes had changed. Then used these events to update the entities.
The entities tracked the changes to the strokes and integrated into the Undo / Redo library. When the user clicked Undo, the library would alter the entities back to their original state. Then I'd push those strokes back into the InkCanvas and trigger a layout update.
Comments and questions are welcome on the codeplex site ( http://muf.codeplex.com/ ). You'll also find complete documentation and sample apps there.
I know its too late but if someone is here for InkCanvas only than this answer might help:
public partial class MainWindow : Window
{
System.Windows.Ink.StrokeCollection _added;
System.Windows.Ink.StrokeCollection _removed;
private bool handle = true;
public MainWindow()
{
InitializeComponent();
inkCanvas1.Strokes.StrokesChanged += Strokes_StrokesChanged;
}
private void Strokes_StrokesChanged(object sender, System.Windows.Ink.StrokeCollectionChangedEventArgs e)
{
if(handle)
{
_added = e.Added;
_removed = e.Removed;
}
}
private void Undo(object sender, RoutedEventArgs e)
{
handle = false;
inkCanvas1.Strokes.Remove(_added);
inkCanvas1.Strokes.Add(_removed);
handle = true;
}
private void Redo(object sender, RoutedEventArgs e)
{
handle = false;
inkCanvas1.Strokes.Add(_added);
inkCanvas1.Strokes.Remove(_removed);
handle = true;
}
}
And in XAML:
<InkCanvas x:Name="inkCanvas1" Width="100" Height="100" Background="Yellow"/>
<Button Content="Undo" Click="Undo" />
<Button Content="Redo" Click="Redo"/>
I don't know if this helps.. But one very easy way to UNDO is:
YourWindow.xaml.cs
private void Undo_Click(object sender, RoutedEventArgs e)
{
if (YourInkCanva.Strokes.Count > 0)
{
YourInkCanva.Strokes.RemoveAt(YourInkCanva.Strokes.Count - 1);
}
else
{
// Else Do Nothing.
}
}
You would want to replace YourInkCanva with the name of your inkcanva.

Problems using inheritance with drag and drop in WPF

I have a usercontrol that I want to implement a drag and drop interface on, here are the vital parts of the implementation, and this works fine:
XML-file to the usercontrol to be draggable:
<UserControl
...default xmlns...
MouseLeftButtonDown="Control_MouseLeftButtonDown">
...GUI-ELEMENTS in the control...
</UserControl>
Code behind:
public partial class DragableControl : UserControl
{
private void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragDrop.DoDragDrop(this, this, DragDropEffects.Move);
}
}
XML-file to the usercontrol which will be able to accept a drag and drop operation:
<Usercontrol
...default xmlns...>
<Grid AllowDrop="True" Drop="Grid_Drop">
... GUI elements in the grid....
</Grid>
</Usercontrol>
Code behind:
public partial class DropClass: UserControl
{
private void Grid_Drop(object sender, DragEventArgs e)
{
var control = (DragableControl)e.Data.GetData(typeof(DragableControl));
if(control != null)
{
//do something
}
}
}
To be able to create different usercontrols which have drag and drop functionality, I creates a base class, BaseDragableUserControl, which at the moment contains nothing, but inherits from usercontrol.
Code:
public class BaseDragableUserControl: UserControl
{
}
I change my code (both xaml and code):
public partial class DragableControl : UserControl
I also changes the class for receiving to this:
public partial class DropClass: UserControl
{
private void Grid_Drop(object sender, DragEventArgs e)
{
var control =(BaseDragableUserControl)e.Data.GetData(typeof(BaseDragableUserControl));
if(control != null)
{
//do something
}
}
}
But the control variable is always Null. I guess that the getdata in the DragEventsArgs does not like inheritance. Is there a way to achieve this? To make it possible to use a base class for a drag and drop class?
Instead of passing this when you initiate the drag/drop, create one of the standard containers for that purpose. Specifically:
DragDrop.DoDragDrop(this, new DataObject("myFormat", this), DragDropEffects.Move);
and then now you know to expect a specific kind of data:
var control =(BaseDragableUserControl)e.Data.GetData("myFormat");

Loading and binding a serialized view model to a WPF window?

I'm writing a one-window UI for a simple ETL tool. The UI consists of the window, the code behind for the window, a view model for the window, and the business logic. I wanted to provide functionality to the users to save the state of the UI because the content of about 10-12 text boxes will be reused between sessions, but are specific to the user. I figured I could serialize the view model, which contains all the data from the textboxes, and this works fine, but I'm having trouble loading the information in the serialized XML file back into the text boxes.
Constructor of window:
public ETLWindow()
{
InitializeComponent();
_viewModel = new ViewModel();
this.DataContext = _viewModel;
_viewModel.State = Constants.STATE_IDLE;
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
XAML:
<TextBox x:Name="targetDirectory"
IsReadOnly="true"
Text="{Binding TargetDatabaseDirectory, UpdateSourceTrigger=PropertyChanged}"/>
ViewModel corresponding property:
private string _targetDatabaseDirectory;
[XmlElement()]
public string TargetDatabaseDirectory
{
get { return _targetDatabaseDirectory; }
set { _targetDatabaseDirectory = value; OnPropertyChanged(DataUtilities.General.Utilities.GetPropertyName(() => new ViewModel().TargetDatabaseDirectory)); }
Load event in code behind:
private void loadState_Click(object sender, RoutedEventArgs e)
{
string statePath = this.getFilePath();
_viewModel = ViewModel.LoadModel(statePath);
}
As you can guess, the LoadModel method deserializes the serialized file on the user's drive.
I couldn't find much on the web regarding this issue. I know this probably has something to do with my bindings. Is there some way to refresh on the bindings on the XAML after I deserialize the view model? Or perhaps refresh all properties on the view model? Or am I completely insane thinking any of this could be done?
Thanks.
Assuming that your loadState_Click event is on the Window code behind you could try this.
private void loadState_Click(object sender, RoutedEventArgs e)
{
string statePath = this.getFilePath();
this.DataContext = ViewModel.LoadModel(statePath);
}

Multiple Command Binding

Is it possible to bind the multiple commands to the button.
I have a user control, which i am calling in my main application (parent application).
I want to handle a click command on both the controls (the user control as well as on the main window). However i am only able to get one.
Is there any way in which i can get this.
Any help is really appreciated.
Code Snippet:
public class MainWindowFooterCommands
{
public static readonly RoutedUICommand FooterClickLocalCommand = new RoutedUICommand("Local Button Command", "FooterClickLocalCommand", typeof(MainWindowFooterCommands));
}
private void MainWindowFooterBindCommands()
{
CommandBinding cmdBindingBXClick = new CommandBinding(MainWindowFooterCommands.FooterClickLocalCommand);
cmdBindingBXClick.Executed += ClickCommandHandler;
CommandBindings.Add(cmdBindingBXClick);
}
void ClickCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
//Do Something
}
//Parent Control holding an instance of the footer control.
class MainWindow {
public MainWindow()
{
CommandBinding cmdBindingBXClick1 = new CommandBinding(MainWindowFooterCommands.BXClickMainWindowCommand);
cmdBindingBXClick1.Executed += LoadParent;
CommandBindings.Add(cmdBindingBXClick1);
}
public void LoadParent(object sender, ExecutedRoutedEventArgs e)
{
LoadParentWindow();
}
}
Regards,
Tushar
You might be trying to aggregate multiple commands, which is a natural thing to want to do.
If you are using Prism, there is a class builtin for this called the CompositeCommand (scroll down a bit): https://msdn.microsoft.com/en-us/library/ff921126.aspx
Otherwise, Josh Smith has a very good article on his implementation called a "Command Group": http://www.codeproject.com/KB/WPF/commandgroup.aspx
There are some very nice scenarios you can rollup like this (for instance, "Save All"). A good tool for your bag of tricks.
AFAIK WPF doesnt offer anything out of the box to support multiple commandbindings at various levels, but you could try the following:
void ClickCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
IInputElement parent = (IInputElement) LogicalTreeHelper.GetParent((DependencyObject)sender);
MainWindowFooterCommands.BXClickMainWindowCommand.Execute(e.Parameter, parent);
}
You might have to test whether your parent really is an IInputElement, though.

Resources