I'm using Robert Gieseckes great Unmanaged Exports to call a c#-Dll from Delphi2006. All works well if I use simple procedures and functions with input and output.
But now I would like to show a Wpf-Window via the call to OpenMyWindow().
Here I get an "External Exception E0434352".
I have no idea why this is not working. Anyway I think it has something to do with Initialization on the wpf side.
Here is the Delphi Code:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, StdCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;
procedure OpenMyWindow(); stdcall; external 'ClassLibraryToDelphi.dll';
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
OpenMyWindow();
end;
end.
and now the c# part (it's a ClassLibrary with an UserControl changed to window):
using System.Linq;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
namespace ClassLibraryToDelphi
{
public static class Test
{
private static UserControl1 myWindow;
[DllExport]
public static void OpenMyWindow()
{
myWindow = new UserControl1();
myWindow.ShowDialog();
}
}
}
Here's the xaml:
<Window x:Class="ClassLibraryToDelphi.UserControl1"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="WPF Window called from Delphi!" />
</Grid>
</Window>
and Codebehind:
using System.Windows;
namespace ClassLibraryToDelphi
{
public partial class UserControl1 : Window
{
public UserControl1()
{
InitializeComponent();
}
}
}
I think it's nothing special or too complicated to reproduce.
It would be great if Robert see this question (any other answer are appreciated too).
Thank you
It's quite simple to do that.
Under the Build-Tab in your Project-Options you have to select 'Register for COM interop' and under Signing you must enter a strong name.
Than you get a tlb-file for your dll.
In Delphi you have to go to 'Component import' and add the tlb-file to your Project. In the dpr-file you have to add Set8087CW($133F) bevor Application.Initialize to disable floating point exceptions.
That's it!
Based on the answer from user3016412 I have tried to add the Set8087CW($133F) procedure call. That was enough for me.
Related
I'm working through the book Head First C# and consistently have issues when adding resources to a window. This is a 100% repeatable error on any new WPF application I create when adding a new resource. The only way around this is to comment out the resource, build, and uncomment, as detailed in MVCE below. Images are included as proof this isn't a what-if or theoretical scenario.
What are the proper steps to add a resource file and use it within a WPF project?
I'm using Visual Studio Community 2017: Version 15.9.9
Target framework: .NET Framework 4.6.1
MVCE:
Create a new WPF application. Add a class:
//MyDataClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XAMLBuildErrorExample
{
class MyDataClass
{
public string Foo { get; set; }
}
}
Within MainWindow.xaml add a resource
<Window x:Class="XAMLBuildErrorExample.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:XAMLBuildErrorExample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:MyDataClass x:Key="exampleResource" />
</Window.Resources>
<Grid>
</Grid>
</Window>
Attempt to build. Error "The tag 'MyDataClass' does not exist in XML namespace 'clr-namespace:XAMLBuildErrorExample'. Line 11 Position 10.":
Comment out the resource. Build succeeds:
Uncomment resource. Build succeeds whereas it failed before:
Any subsequent cleaning of the solution makes building impossible because of the error in the first image.
It appears the problem is tied to initial computer.
Tested on another work station VS Community 2017 version 15.9.11 and build was successful without any issues. Build>Clean>Build without issues.
I am very new to WPF programming, so please forgive if this is an obvious mistake on my part. I have a UserControl object that has the following Xaml:
<UserControl x:Class="SDMAS.LOOPAnalyzer.Views.Workspace"
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:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:local="clr-namespace:SDMAS.LOOPAnalyzer.Models" >
<UserControl.Resources>
<!-- create an instance of our DataProvider class -->
<ObjectDataProvider x:Key="tblLOOPDataProvider" ObjectType="{x:Type local:tblLOOPDataProvider}"/>
<!-- define the method which is invoked to obtain our data -->
<ObjectDataProvider x:Key="LOOPEvents" ObjectInstance="{StaticResource tblLOOPDataProvider}" MethodName="GetData"/>
</UserControl.Resources>
<DockPanel DataContext="{Binding Source={StaticResource LOOPEvents}}">
<dg:DataGrid ItemsSource="{Binding}" Name="dataGrid"/>
</DockPanel>
</UserControl>
This code actually works. The records from the data table are correctly displayed in the application's view. The problem is the Visual Studio designer for this control thinks there is a problem, complaining about not being able to find the object type in the namespace: ObjectType="{x:Type local:tblLOOPDataProvider}"
The namespace does exist, and does contain the class, as proven by the fact the code is working. So what gives with the designer?
The following is screenshot of the error message:
Here is the tblLOOPDataProvider code
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SDMAS.LOOPAnalyzer.Models.LOOPDataSetTableAdapters;
namespace SDMAS.LOOPAnalyzer.Models
{
/// <summary>
/// Provides a singleton instance of the LOOPDataSet
/// </summary>
public class LOOPDataProvider
{
private static LOOPDataSet _loopDataSet;
public static LOOPDataSet LOOPDataSet
{
get
{
if (_loopDataSet == null)
{
_loopDataSet = new LOOPDataSet();
}
return _loopDataSet;
}
}
}
/// <summary>
/// A source of LOOP event objects
/// </summary>
public class tblLOOPDataProvider
{
private tblLOOPTableAdapter _adapter;
public tblLOOPDataProvider()
{
LOOPDataSet dataset = LOOPDataProvider.LOOPDataSet;
_adapter = new tblLOOPTableAdapter();
_adapter.Fill(LOOPDataProvider.LOOPDataSet.tblLOOP);
dataset.tblLOOP.tblLOOPRowChanged += new LOOPDataSet.tblLOOPRowChangeEventHandler(tblLOOPRowModified);
dataset.tblLOOP.tblLOOPRowDeleted += new LOOPDataSet.tblLOOPRowChangeEventHandler(tblLOOPRowModified);
}
void tblLOOPRowModified(object sender, LOOPDataSet.tblLOOPRowChangeEvent e)
{
_adapter.Update(LOOPDataProvider.LOOPDataSet.tblLOOP);
}
public DataView GetData()
{
return LOOPDataProvider.LOOPDataSet.tblLOOP.DefaultView;
}
}
}
Since I first posted this I have been hacking at various parts of the project, and now the designer won't display the Xaml at all. Just says Loading Designer... and appears to hang.
Some more background. I started this project based on the Prism4Demo on CodeProject (by David Veeneman). It has changed much since it's beginning, migrating to Prism 6 and updating other dependencies. That demo seemed a good template for an application that will have a number of modules to be developed independently by different staff members, likely with only one professional programmer to provide integration (not me). The class creating the designer problem is the "workspace" view for one of the modules that will eventually be wired to a view-model that in turn will be wired to a model consisting of a DataSet representing a LOOP event data table on a SQL server. In this current learning step, I have connected the server data table to a DataSet, which I am displaying in the workspace view directly without the view-model in the middle (and it is working, aside from the designer issue). I have based the code on internet examples that I don't yet understand all the way, but have been able to make work. So I don't yet understand the reason for the LOOPDataProvider class complexity, or the use of Resources in the Xaml.
So I continue to study the MVVM structure and my next step will be to wire up the DataSet-based model to the view-model, and the view-model to the view.
I have really strange problem. I've created WPF project in 2012 or 2013 VS it doesn't matter. I use .NET 4.5.
I add a new Activity (Workflow class) to that project. Its name is CustomActivity.
Then I add a new class that has got an attached property, example below:
public class AttachedObject : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.RegisterAttached(
"Name",
typeof(string),
typeof(AttachedObject),
new FrameworkPropertyMetadata(
string.Empty,frameworkPropertyMetadataOptions.AffectsRender));
public static void SetName(ContentControl element, string value)
{
element.SetValue(NameProperty, value);
}
public static string GetName(ContentControl element)
{
return (string)element.GetValue(NameProperty);
}
}
The last step is to change MainWindow class that way:
public MainWindow()
{
InitializeComponent();
var activity = new CustomActivity();
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1;assembly=WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ContentControl wpfApplication1:AttachedObject.Name="MainArea"/>
</Grid>
</Window>
The problem is it doesn't compile because of below error:
Error 1 The type or namespace name 'CustomActivity' could not be found (are you missing a using directive or an assembly reference?) WpfApplication1\MainWindow.xaml.cs 13 32 WpfApplication1
CustomActivity has a default namespace. In obj folder there is CustomActivity.g.cs generated, so I have no idea what's going on.
It's 100% reproducible. When I remove using of CustomActivity or using of AttachedObject from xaml then the problem disappear.
Try replacing this:
xmlns:wpfApplication1="clr-namespace:WpfApplication1;assembly=WpfApplication1"
with this
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
The error you're seeing is due to a "known" issue in WPF applications that xaml namespaces that reference clr namespace from current assembly your in don't require the full assembly qualified name. If you were to declare a xaml namespace that references a clr namespace from another assembly, than you would have to specify the full name (with the ;[assemblyname] syntax).
Workflow Foundation has nothing to do with it.
EDIT:
Didn't realize it was a xaml activity.
But still, you can make it work, maybe, with a few hacks, but I wouldn't recommend it.
The reason you get that error is due to the different code generation and build action VS uses when creating xaml artifacts for WPF (Page):
System.Windows.Application.LoadComponent(this, resourceLocater);
and when creating xaml activities (XamlAppDef):
typeof(CustomActivity).Assembly.GetManifestResourceStream(resourceName);
If you turn your CustomActivity xaml build action to Page, the whole thing will compile - but i'm guessing something else might be broken someplace else...or not, who knows. My guess is that these two kinds of xaml were not meant to live together in a VS WPF application project template. But you can still define activities in a WF activity library, that way your activities will also be more easily reusable for other projects, WPF, console or even services.
I have the same issue under Visual Studio 2017.
The problem in my case is that Visual Studio is not compiling the Workflow activities before the code that use them.
To fix it, what I did is to move all workflows to other project dll, so visual Studio is forced to compile the workflows before the classes that make use of them.
I am wondering if anyone might be able to give me a little help with xinput (for and Xbox controller) and vb.net.
What I am trying to do is translate the analog stick motions to certain events in my application. Specifically what I am trying to do is move a map when the joystick is moved.
Is it possible to use the xinput with vb.net? I'm stuck in either vb or c# based on what the COM libraries are for the application. Any attempts to add the DLL's just throws an error at me too.
Thanks for any help,
Cheers!
You can also look into http://sharpdx.org/
It's a managed XInput library. Connecting to a controller is easy:
var controller = new SharpDX.XInput.Controller(SharpDX.XInput.UserIndex.One);
if (controller.IsConnected)
{
var state = controller.GetState();
var x = state.Gamepad.LeftThumbX;
var y = state.Gamepad.LeftThumbY;
}
SharpDX is available as nuget package
You can achieve that with MonoGame, here's a small example of a WPF application reading the value of the left thumb stick.
<Window x:Class="GamePadTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock x:Name="TextBlock1"></TextBlock>
</Grid>
</Window>
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace GamePadTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
var gamePadState = GamePad.GetState(PlayerIndex.One);
TextBlock1.Text = gamePadState.ThumbSticks.Left.ToString();
}
}
}
How did I do that ?
Installed MonoGame : https://monogame.codeplex.com/
Created a new WPF project and referenced "C:\Program Files (x86)\MonoGame\v3.0\Assemblies\Windows8\MonoGame.Framework.dll"
Do not forget to copy SDL.DLL to your bin\Debug, grab it here: http://www.libsdl.org/release/SDL-1.2.15-win32.zip
(done under Windows 8 x64 + Visual Studio 2012)
Does anyone know of some global state variable that is available so that I can check if the code is currently executing in design mode (e.g. in Blend or Visual Studio) or not?
It would look something like this:
//pseudo code:
if (Application.Current.ExecutingStatus == ExecutingStatus.DesignMode)
{
...
}
The reason I need this is: when my application is being shown in design mode in Expression Blend, I want the ViewModel to instead use a "Design Customer class" which has mock data in it that the designer can view in design mode.
However, when the application is actually executing, I of course want the ViewModel to use the real Customer class which returns real data.
Currently I solve this by having the designer, before he works on it, go into the ViewModel and change "ApplicationDevelopmentMode.Executing" to "ApplicationDevelopmentMode.Designing":
public CustomersViewModel()
{
_currentApplicationDevelopmentMode = ApplicationDevelopmentMode.Designing;
}
public ObservableCollection<Customer> GetAll
{
get
{
try
{
if (_currentApplicationDevelopmentMode == ApplicationDevelopmentMode.Developing)
{
return Customer.GetAll;
}
else
{
return CustomerDesign.GetAll;
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
I believe you are looking for GetIsInDesignMode, which takes a DependencyObject.
Ie.
// 'this' is your UI element
DesignerProperties.GetIsInDesignMode(this);
Edit: When using Silverlight / WP7, you should use IsInDesignTool since GetIsInDesignMode can sometimes return false while in Visual Studio:
DesignerProperties.IsInDesignTool
Edit: And finally, in the interest of completeness, the equivalent in WinRT / Metro / Windows Store applications is DesignModeEnabled:
Windows.ApplicationModel.DesignMode.DesignModeEnabled
You can do something like this:
DesignerProperties.GetIsInDesignMode(new DependencyObject());
public static bool InDesignMode()
{
return !(Application.Current is App);
}
Works from anywhere. I use it to stop databound videos from playing in the designer.
There are other (maybe newer) ways of specifying design-time data in WPF, as mentioned in this related answer.
Essentially, you can specify design-time data using a design-time instance of your ViewModel:
d:DataContext="{d:DesignInstance Type=v:MySampleData, IsDesignTimeCreatable=True}"
or by specifying sample data in a XAML file:
d:DataContext="{d:DesignData Source=../DesignData/SamplePage.xaml}">
You have to set the SamplePage.xaml file properties to:
BuildAction: DesignData
Copy to Output Directory: Do not copy
Custom Tool: [DELETE ANYTHING HERE SO THE FIELD IS EMPTY]
I place these in my UserControl tag, like this:
<UserControl
...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
...
d:DesignWidth="640" d:DesignHeight="480"
d:DataContext="...">
At run-time, all of the "d:" design-time tags disappear, so you'll only get your run-time data context, however you choose to set it.
Edit
You may also need these lines (I'm not certain, but they seem relevant):
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
When Visual Studio auto generated some code for me it used
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
...
}
And if you extensively use Caliburn.Micro for your large WPF / Silverlight / WP8 / WinRT application you could use handy and universal caliburn's Execute.InDesignMode static property in your view-models as well (and it works in Blend as good as in Visual Studio):
using Caliburn.Micro;
// ...
/// <summary>
/// Default view-model's ctor without parameters.
/// </summary>
public SomeViewModel()
{
if(Execute.InDesignMode)
{
//Add fake data for design-time only here:
//SomeStringItems = new List<string>
//{
// "Item 1",
// "Item 2",
// "Item 3"
//};
}
}
Accepted answer didn't work for me (VS2019).
After inspecting what was going on, I came up with this:
public static bool IsRunningInVisualStudioDesigner
{
get
{
// Are we looking at this dialog in the Visual Studio Designer or Blend?
string appname = System.Reflection.Assembly.GetEntryAssembly().FullName;
return appname.Contains("XDesProc");
}
}
I've only tested this with Visual Studio 2013 and .NET 4.5 but it does the trick.
public static bool IsDesignerContext()
{
var maybeExpressionUseLayoutRounding =
Application.Current.Resources["ExpressionUseLayoutRounding"] as bool?;
return maybeExpressionUseLayoutRounding ?? false;
}
It's possible though that some setting in Visual Studio will change this value to false, if that ever happens we can result to just checking whether this resource name exist. It was null when I ran my code outside the designer.
The upside of this approach is that it does not require explicit knowledge of the specific App class and that it can be used globally throughout your code. Specifically to populate view models with dummy data.
I have an idea for you if your class doesn't need an empty constructor.
The idea is to create an empty constructor, then mark it with ObsoleteAttribute. The designer ignores the obsolete attribute, but the compiler will raise an error if you try to use it, so there's no risk of accidentaly using it yourself.
(pardon my visual basic)
Public Class SomeClass
<Obsolete("Constructor intended for design mode only", True)>
Public Sub New()
DesignMode = True
If DesignMode Then
Name = "Paula is Brillant"
End If
End Sub
Public Property DesignMode As Boolean
Public Property Name As String = "FileNotFound"
End Class
And the xaml:
<UserControl x:Class="TestDesignMode"
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:vm="clr-namespace:AssemblyWithViewModels;assembly=AssemblyWithViewModels"
mc:Ignorable="d"
>
<UserControl.Resources>
<vm:SomeClass x:Key="myDataContext" />
</UserControl.Resources>
<StackPanel>
<TextBlock d:DataContext="{StaticResource myDataContext}" Text="{Binding DesignMode}" Margin="20"/>
<TextBlock d:DataContext="{StaticResource myDataContext}" Text="{Binding Name}" Margin="20"/>
</StackPanel>
</UserControl>
This won't work if you really need the empty constructor for something else.