Putting a WPF UserControl on the TaskPane of an Excel2007 Addin - wpf

I am making a Excel Addin in VS2010.
The following code work fines if I make a winforms usercontrol
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
var testControlView1 = new UserControl1();
var MyCustomPane = this.CustomTaskPanes.Add(testControlView, "Hello");
}
However I would like to make my UserControl1 be a WPF UserControl. Does anybody know how I would achieve similar functionality or an alternate approach?
As far as I can tell the CustomTaskPanes only allows Winforms Controls to be added to it.

Answer summary:
1. Add a .net winforms usercontrol
2. Add a SWF.Integration.ElementHost control to the user control.
3. Add a Wpf control to your project seperately (not to the user control).
3. Use the Hosted Content property (hostedcontentName) of the ElementHost control and set it to the wpf control.

I found this blog post that answered it great...

Related

WPF How to handle Cut, Copy, Paste toolbar buttons with UserControls and WindowsFormsHost

I'm hoping someone out there can help me. I'm trying to convert a legacy winforms app to WPF using MVVM. I've broken up the main window of the application into 4 main UserControls. The UserControls display different types of data objects and each UserControl has it's own ViewModel. Some of the data objects are inter-changeable between the different UserControls, for instance 'User Control 1' can contain strings objects and so can 'User Control 2 and 'User Control 3' (see diagram below).
My question is how can I handle the Cut, Copy, Paste commands in the toolbar? To possibly make things more complicated, each UserControl can contain a selected object at the same time as the other UserControls contain a selected object and User Control 2 is a WindowsFormsHost wrapper around a winforms control.
So far I've tried using ApplicationCommands but I can't even get them to fire. I've pasted a snippet of the code I thought would work using the ApplicationCommands below. Any help with this would be really appreciated.
<Button Command="ApplicationCommands.Cut" />
and on the UserControls
<UserControl.CommandBindings>
<CommandBinding Command="ApplicationCommands.Cut" Executed="executed_Cut" CanExecute="canExecute_Cut" />
</UserControl.CommandBindings>
and finally in the UserControl's code behind (I know this isn't great)
public void executed_Cut(Object sender, ExecutedRoutedEventArgs e)
{
//execute code here
}
public void canExecute_Cut(Object sender, CanExecuteRoutedEventArgs e)
{
//can execute code here
}
I successfully use the behavior approach described in this question to avoid putting any code in my view model. Then whenever focus goes to a control which has a copy/paste behavior defined the toolbar cut/copy/paste buttons "light up" accordingly.

ActiveX Control In WPF Windows Form Host Not Displaying After Becoming Visible

I have a wpf usercontrol that contains an activex control housed in a windowsformhost.
I'm using an MVVM pattern that says
ViewModel1 is mapped to a Pure WPF View and
ViewModel2 is mapped to wpf content and the above usercontrol
If ViewModel2 is "Hidden" and then becomes Visible then the Activex control inside it doesn't show (Specifically I'm talking about the VLC activex control).
I've tested in a non MVVM pattern with a button and the usercontrol. The usercontrol is hidden until you press the button and the same thing happens but if I create a method in the usercontrol to re attach the activex control to the windowsformhost then it reappears. If I call this method from a viewmodel then it still remains blank. Does anyone know how I can get this to show again?
EDIT - I've just discovered it's because I have transparency on in my wpf application. It seems it's not possable to do what I want with windowsformshost and transparency enabled.
As there are no obvious answers I'll share my experience. When transparency is turned on in the wpf window then the windows form host doesn't refresh when changing from Hidden to Visable. I have found no way to make this work unless it is hosted in a new window with "Allowstransparency=false".
How are you setting up your active x control? The following Typically works for me in WPF if you are just needing it to attach to a grid. No user control required.:
//Active X Control initializer
private Ax addAxObject<Ax>(Grid container)
where Ax : System.Windows.Forms.Control, new()
{
Ax ax = new Ax();
var hoster = new System.Windows.Forms.Integration.WindowsFormsHost();
hoster.Child = (System.Windows.Forms.Control)ax;
container.Children.Add(hoster);
return ax;
}
private MyActiveXControl myActiveXControl;
public Grid InitializeActiveX(Grid grid)
{
myActiveXControl = addAxObject<myActiveXControl>(grid);
return grid;
}
Then all you do is is add it to your grid in your main window like so:
public MainWindow()
{
InitializeComponent();
//initialize Active X control
gridMain = InitializeActiveX(gridMain);
}
It shows up just fine for me. (Obviously not in the designer since it is programatically created)

Add a WPF UserControl to a TaskPane

I am developing an addin to Microsoft Outlook.
The following code works fine if I use an winforms UserControl:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
var testControlView1 = new UserControl1();
var MyCustomPane = this.CustomTaskPanes.Add(testControlView, "Hello");
}
How can I do it with a WPF UserControl, instead? Does anybody know how I would achieve similar functionality?
As far as I can tell the CustomTaskPanes only allow Winforms Controls to be added to it.
Just found a solution,
https://stevepietrekweblog.wordpress.com/2009/03/24/vsto-display-wpf-user-control-in-custom-task-pane/
This update was just to update the link.

Hosting ActiveX control in WPF

I have an ActiveX control (written in Delphi) which I want to host in a WPF application. When I try to load it into the toolbox to add it to the XAML at design time, it is not shown in the list of available controls. Does anyone know what filters this list and why I can't see the control to add it?
Edit
This is where I get to - the host.Child = (ax); statement gets an error (Cannot implicitly convert type 'DemoFrameControl.DemoFrameCtrl' to 'System.Windows.Forms.Control'), hope this helps clarify my problem
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// Create the interop host control.
System.Windows.Forms.Integration.WindowsFormsHost host =
new System.Windows.Forms.Integration.WindowsFormsHost();
// Create the ActiveX control.
DemoFrameControl.DemoFrameCtrl ax = new DemoFrameControl.DemoFrameCtrl();
// Assign the ActiveX control as the host control's child.
host.Child = (ax);
// Add the interop host control to the Grid
// control's collection of child controls.
this.grid1.Children.Add(host);
// Play a .wav file with the ActiveX control.
//axWmp.URL = #"C:\WINDOWS\Media\Windows XP Startup.wav";
}
Thanks
Check out Walkthrough: Hosting an ActiveX Control in WPF.
Update:
How is DemoFrameCtrl defined? Like the error says, it needs to be a subclass of System.Windows.Forms.Control to use WindowsFormsHost. An ActiveX control wrapper will inherit from AxHost which inherits from Control. I think Visual Studio will generate the wrapper if you add a reference to the ActiveX library. If not, you can try using Aximp.exe (Windows Forms ActiveX Control Importer).

Dynamic Application-level resources are not dynamic when hosted in ElementHost

I'm hosting a WPF UserControl in a WinForms container. Now, I want to be able to theme/skin the UserControl. To do this, I've got several resource dictionaries that define the "skins." When my app starts up I create a "new System.Windows.Application()" so that Application.Current exists. To change the theme the old skin is removed and a new skin is merged into the Application level resource dictionary at runtime. However, this does not change any of the dyanamically referenced resources in the UserControl. I tried this in a straight WPF application and it worked just fine. Am I missing something, or is it not possible to do this at all? By the way, if I add a skin into the application resources before the UserControl is initialized it will work but I cannot change the skin after that.
To repo this in the most basic way:
Create a new WinForms application. Add a WPF UserControl to the app. This is simple enough:
<UserControl ...>
<Grid>
<Button
Background="{DynamicResource ButtonBG}"/>
</Grid>
</UserControl>
Create two ResourceDictionaries, White.xaml and Black.xaml (or whatever) that have a SolidColorBrush with the key ButtonBG with respective color. In Form1.cs, add two Buttons and an ElementHost. Set the child of the ElementHost to an instance of the UserControl we just created. Wire up the buttons to events that swap the skin:
private void White_Click(object sender, EventArgs e)
{
Application.Current.Resources.MergedDictionaries[0] =
(ResourceDictionary)Application.LoadComponent(
new Uri(#"\WpfThemes;component\White.xaml", UriKind.Relative)));
}
private void Black_Click(object sender, EventArgs e)
{
Application.Current.Resources.MergedDictionaries[0] =
(ResourceDictionary)Application.LoadComponent(
new Uri(#"\WpfThemes;component\Black.xaml", UriKind.Relative)));
}
In Program.cs, ensure that Application.Current exists and set the initial skin:
[STAThread]
static void Main()
{
new System.Windows.Application();
Application.Current.Resources.MergedDictionaries[0] =
(ResourceDictionary)Application.LoadComponent(
new Uri(#"\WpfThemes;component\White.xaml", UriKind.Relative)));
...
}
Now, when the White button is clicked I would expect the button in the UserControl to turn white and when the Black button is clicked I would expect the button to turn black. This does not happen, however.
Does anyone know why? Is there a solution?
Edit: Idea: Perhaps, if there's a way to force re-evaluation of DynamicResources when the theme changes, that would work.
Thanks,
Dusty
I think this may be an overlooked issue in the WPF framework.
From what I can tell via Reflector, it appears that when the Application resource dictionary is catastrophically changed (a change that will likely have wide ranging effects like adding, removing, or replacing a skin), there is code that loops over all of the Windows in the application and forces them to re-evaluate their DynamicResources. However, other elements that I would consider top-level in WPF like ElementHosts do not get the same treatment. This leads to the behavior that I'm experiencing.
My workaround to this issue is to manually go through all of my ElementHosts individually and add, remove, or replace the skin ResourceDictionary file. It's not perfect, but it gets the job done.
Dr. WPF came to my rescue when I was trying to do something similar. He shows how to create the Application object in WinForms. Now you can reference everything as StaticResource just like in a WPF application.
http://drwpf.com/blog/2007/10/05/managing-application-resources-when-wpf-is-hosted/
Another workaround would be to create a dummy window and specify the content of the elementhost as content.
If you look into the Application and check how it handles changes of resourcedictionaries, you see that it only notifies windows..
The only thing you should remind is to never show the window (-> exception), and to close it when disposing the elementhost, so the application can shutdown properly.

Resources