adding WindowsFormsHost control to MainWindow causes to crash the exe - wpf

I'm using WPF in F# via FsXaml. The MainWindow works, until I add a WindowsFormsHost control, at which point it will crash with the following error when executed:
Unhandled Exception: System.Xaml.XamlObjectWriterException: Cannot create unknown type '{http://schemas.microsoft.com/winfx/2006/xaml/presentation}WindowsFormsHost'.
at System.Xaml.XamlObjectWriter.WriteStartObject(XamlType xamlType)
at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
at FsXaml.InjectXaml.from$cont#37(String file, Object root, Stream resStream, Unit unitVar)
at FsXaml.InjectXaml.from(String file, Object root)
at Program.Win.InitializeComponent()
at Program.Win..ctor()
Is there anything I need to add the xaml or the app to recognize the winformshost? The C# generated xaml works in a C# app. The F# app works if there is no winformshost inside it. The difference between the C# and F# xamls is the x-local namespace reference.
The MainWindow.xaml:
<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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Height="124" VerticalAlignment="Top" Width="217"/>
<WindowsFormsHost HorizontalAlignment="Left" Height="123" Margin="49,171,0,0" VerticalAlignment="Top" Width="394"/>
</Grid>
</Window>
The App.xaml
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
Program.fs:
open System
open System.Windows
open FsXaml
open Microsoft.FSharp.Control
open System.Windows.Forms
open System.Windows.Forms.Integration
open FSharp.Charting
open FSharp.Charting.ChartTypes
type App = XAML<"App.xaml">
type Win = XAML<"MainWindow.xaml">
[<STAThread>]
[<EntryPoint>]
let main _ =
let app = App()
let win = Win()
win.button.Content <- "Click!"
win.button.MouseRightButtonDown.Add (fun _ -> MessageBox.Show("OK") |> ignore)
app.Run win |> ignore
0

Try explicitly adding the namespace (using clr-namespace), the same way you would for the winforms controls themselves - just use System.Windows.Forms.Integration. I assume that isn't included in the default XAML namespace :)
xmlns:wfi="clr-namespace:System.Windows.Forms;assembly=WindowsFormsIntegration"

Related

How can I set region Manager for my dialog window in Prism?

I write my app without using Shell. So I created my own Window using IDialogService and opened in one of my modules.
As far, as I am concerned, Region Manager is attached to Shell, but due to the fact I don't have it, region manager doesn't work when I try to navigate from one view to another.
I know that Region Navigation works fine with the shell (I tested it) and the same code stops working when I substitute the shell with IDialogService.
Here is what I have
<Window x:Class="TechDocs.Views.MainSettingsWindowView"
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:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="MainSettingsWindow" Height="400" Width="750">
<Grid>
</Grid>
</Window>
Content for the first region. When I click the button, it should navigate to the second region.
<UserControl x:Class="TechDocs.Views.SettingsView"
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:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Button Command="{Binding NodeSelectedCommand}" Name="Button"/>
<ContentControl prism:RegionManager.RegionName="region"/>
</Grid>
</UserControl>
In module I connect my root window with UserControl which holds the button and Content control for the second region.
public class SettingsModule : IModule
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
var dialogService = _containerProvider.Resolve<IDialogService>();
containerRegistry.RegisterDialog<MainSettingsWindow>("MyWindow");
containerRegistry.RegisterDialog<SettingsView>("customView");
containerRegistry.RegisterForNavigation<MyView>();
dialogService.Show("customView");
}
}
And when I click the button I get in this code
public void SelectedNode()
{
regionManager.RequestNavigate("region", "MyView");
}
RequestNavigate doesn't give any exceptions, but still nothing appears on the screen.
Could you please explain how I should register region manager with my window?
Try to initialize the region manager explicitly in your custom window using the static methods below:
RegionManager.SetRegionName(cc, "region");
RegionManager.SetRegionManager(cc, regionManager);
XAML:
<ContentControl x:Name="cc" prism:RegionManager.RegionName="region"/>

Can MahApps.Metro be used in MvvmCross?

I was trying to use Mahapps Metro inside a WPF project using MvvmCross mvvm framework.
Both seem to use custom window control. Is there a way to use both in a project?
Metro window:
<mah:MetroWindow x:Class="TipCalc.WPF.MainWindow"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
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:TipCalc.WPF"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Grid>
</Grid>
</mah:MetroWindow>
MvvmCross Window:
<views:MvxWindow x:Class="TipCalc.WPF.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:TipCalc.WPF"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Grid>
</Grid>
</views:MvxWindow>
The application runs either way. But with the Metro window in place, the rest of the application doesn't get set up(ie.-children views). With the MvvmCross window in place, the application works as usual but is not designed or colored.
Since multi inheritance is not supported in C#, this is not possible out of the box.
But a look at the source code of MvxWindow shows it's no big class. So a potential solution could be creation of your own window. This window, let's call it MvxMetroWindow, could collect both functionalities by inheriting from MetroWindow and aditionally all the source code of MvxWindow added (copied from the original source code) by yourself.
This would look like this:
using System;
using System.Windows;
using MahApps.Metro.Controls;
using MvvmCross;
using MvvmCross.Binding.BindingContext;
using MvvmCross.Platforms.Wpf.Views;
using MvvmCross.ViewModels;
using MvxApplication = MvvmCross.Platforms.Wpf.Views.MvxApplication;
namespace TipCalc.WPF
{
public class MvxMetroWindow : MetroWindow, IMvxWindow, IMvxWpfView, IDisposable
{
private IMvxViewModel _viewModel;
private IMvxBindingContext _bindingContext;
private bool _unloaded = false;
//... Further implemenetation of original MvxWindow
}
}
The custom window finally can be used like this:
<local:MvxMetroWindow x:Class="TipCalc.WPF.MainWindow"
xmlns:local="clr-namespace:TipCalc.WPF"
...

Why am I getting an error loading resources/resources.xaml in the designer when I instantiate my WPF user control on a page?

I only get this error in the designer; my game runs just fine.
The error is "Cannot locate resource resources/resources.xaml". It only occurs on views where I reference my user control, and only in the designer - not when I design the user control itself, and not at runtime; I'm able to compile my game just fine even though I have this error.
Here is where I declare my user control instance:
<local:StatsView Grid.ColumnSpan="2" x:Name="stats"/>
And here are the relevant parts of my user control:
<UserControl x:Class="Wormholes.Views.StatsView"
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:Wormholes.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary Source="/Resources/Resources.xaml" />
</UserControl.Resources>
<Grid>
...
</Grid>
</UserControl>
I'm also referencing this same Resources.xaml in each of my pages, in addition to from the user control; could this be causing the error? If so, how do I work around it?
You have used a Relative URI, so it will looks for your resource file in a somewhere that you used your UserControl. It can't find you resource file because your resource file is not in the AbsolutePath.
AbsolutePath = CurrentPath (r.g Where you used your UserControl) + RelativePath
so Use an AbsolutePath:
<ResourceDictionary Source="pack://application:,,,/{YourAssemblyName};component/Resources/Resources.xaml" />

Call method on Window Loaded Event in F# with WPF

I am getting a XAMLParseException when trying to load a xaml component with a Loaded event. I am not quite sure how write the method signature for the handled event. C# examples are clear but I'm not sure how to convert this to the F# version. I will include my first attempt below.
ViewModel code:
let theWindow = Application.LoadComponent(new Uri("/MyApp;component/MyWindow.xaml", UriKind.Relative)) :?> Window
XAML Header:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:MyApp.Converters;assembly=MyApp"
xmlns:local="clr-namespace:MyApp;assembly=MyApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
x:Name="_theWindow"
WindowStartupLocation="CenterOwner"
Title="My App - Popup Window"
Loaded="Window_Loaded"
Icon="MyApp;component/icons/MyApp.ico"
Width="484.667" Height="215.333"
Left="100" Top="100">
F# method:
member x.Window_Loaded (sender : object, eventArgs : RoutedEventArgs) = // Do stuff
When using FsXaml.Wpf v.3.1.3 I had...
StartupUri="MainWindow.xaml"
...in my app.xaml file. I removed it and used this in my App.fs file to open MainWindow.xaml...
[<STAThread>]
[<EntryPoint>]
let main argv =
Wpf.installSynchronizationContext ()
Views.MainWindow()
|> App().Run
...which matches the WpfMvvmAgent demo. That resolved the XamlParseException above for me.

WPF:programmatically add RibbonBar from UserControl into a RibbonWindow RibbonTab

I have a WPF Ribbon based application and a DLL.
In the application I uses a third party source (Syncfusion) to create my RibbonWindow.
The DLL is a WPF class library that consist of a UserControl which is a RibbonBar.
I would like to add that UserControl to my RibbonWindow.
I'm not sure how to do that programmatically.
MainWindow.xaml.cs
Dynamically loaded the UserControl from the DLL
Assembly asm = Assembly.LoadFile( unitDllPath );
Type typ = asm.GetType( "WX" + ".UserControl1", true, true );
unitDll = Activator.CreateInstance( typ );
MainWindow.xaml
<syncfusion:RibbonTab Name="Tab1" IsChecked="True" >
</syncfusion:RibbonTab>
UserControl.xaml
<syncfusion:RibbonBar Header="Select" Name="Bar1" ></syncfusion:RibbonBar>
UserControl.xaml.cs
public void MainWindow()
{
InitializeComponent();
}
How can I get the RibbonBar from WX.UserControl (Bar1) into (Tab1)?
Thanks.
1)If we need to programmatically add UserControl which is a RibbonBar to your RibbonWindow, your UserControl should be like below
UserControl.xaml
<syncfusion:RibbonBar x:Class="WPFClassLibrary.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<syncfusion:RibbonButton SizeForm="Large" Label="New Email"/>
<syncfusion:RibbonButton SizeForm="Large" Label="Inbox"/>
<syncfusion:RibbonButton SizeForm="Large" Label="Drafts"/>
<syncfusion:RibbonButton SizeForm="Large" Label="OutBox"/>
2)Refer the assembly file in your application.
3)use that Assembly in code behind like below
using WPFClassLibrary;
4)now we can call that UserControl from code behind and add to the our RibbonWindow.
tab1.Items.Add(new UserControl1());
i have also attach simple sample for this
http://www.syncfusion.com/downloads/support/directtrac/general/ze/WPfRibbonSample-1343767783

Resources