I'm improving an existent WPF project with a TCP/IP protocol that sends and receive small objects. I'm using Visual Studio 10 but I'm stuck.
I'm using BinaryFormatter to serialize the objects and until I used to send and receive with two classes in the same project I had no problem, but when I separated listener and sender (TCPListener and TCPCLient) on runtime i had this error:
"Can't find Assembly 'ProjectName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'".
Googling I found out that the problem could be solved creating an external dll called from main program, but I don't know how to pass the MainWindow to the dll because the library not even can find WPF types (such as MainWindow, Combobox or Textbox)
Can you help me with this dll problem or do you have any ideas to solve the assembly reference problem?
First of all, you shouldn't pass the MainWindow to a class you intend to serialize. This data class should actually not have any dependencies on the GUI. In fact, if you want to serialize a class, its public interface should in my opinion only contain primitive types or classes defined in the same assembly.
However, for a quick fix, and if you don't want to rewrite your project completely, I found that the easiest way to get the dependencies for a WPF library right was to start a new WPF application project and then change its project type to WPF Class library in the application tab of the project properties.
Related
I am wanting to rewrite one of my Revit Add ins so that it utilizes WPF with MVVM because I like the look and functionality of WPF better than Windows Forms.
I have used the Revit Template Wizzard from Jeremy Tammik for the Form based add in, but adding a WPF user control seems not to work (a run time error that the xaml resource cannot be found).
I found a WPF MVVM revit add in example (AddMaterials, here is the github link, which will add materials from an Excel spreadsheet) but it does not follow what I am expecting to see at the top level.
Revit Add ins have an app.cs file which tells Revit how to register and access the DLL (ribbon panel buttons etc).
A windows WPF app will have app.xaml as the top level entry point.
The Add Materials project has neither which tells me that it must be
a class library, however the views are not using UserControls
rather they are Windows which I prefer. However Visual Studio does not
let you add a Window for a Class Library type project.
The third issue is easily solved by simply copying windows from a WPF application project into a class library project. But I don't really understand how the class library will instantiate in Revit without following the app.cs code from the template. Is anyone else creating add-ins this way, and if so can you let me in on any tricks or discussions that will help? Has anyone created a WPF Revit addin template for Visual Studio?
When I add a WPF window and try to instantiate it I get an error that it cannot find the xaml resource (System.IO.IOException: Cannot locate resource 'xxxx.xaml'). I have tried to fix this according to advice found when googling for this error, but to no avail. I am thinking it comes from being in a form based project, and that I may have to just start with a new project without the form stuff.
I have now verified that indeed you can start with the Revit AddIn Wizzard and use WPF . . . I started from scratch and copied in a window created in another project and got it to run (after adding the various references, namespaces, etc). So my problem seems to just be with the original project which already had a bunch of form stuff added.
Yes, I'm using WPF to create Revit Addins. It works well. You can easily create your own WPF template from the SDK samples:
Start with one of the Autodesk-provided SDK samples. I used the "DockableDialogs" sample. I know this one works, your mileage may vary with the others. If you're looking for windows rather than docked panes in the UI, another sample (perhaps the AddMaterials sample) is probably simpler.
I used Visual Studio to turn the sample into a template. File - Export Template -> select "DockableDialogs" or other WPF sample project.
Create a new project based on the template you just created. This was the easiest method I could find to get the WPF internal bits wired up correctly.
I'm not specifically familiar with the AddMaterials project, but to clarify your bullet points.
Revit Addins - It's not the file name (app.cs) but rather they must extend IExternalApplication or IExternalCommand. If you are creating a xaml interface (rather than just running a command from a ribbon button) you'll use 'IExternalApplication' as your entry point. Look for something like this in the sample:
public class ThisApplication : IExternalApplication ...
I don't used a top level app.xaml, but instead have page.xaml pages which are called by the Revit app. In my case these are Pages rather than Windows, which extend the IDockablePaneProvider class. These must be registered with the application which can then can be show, hide, etc your Panes. I imagine this is simpler with Windows, but haven't done it myself. For the dockable panes, your xaml.cs should start out something like:
public partial class MainPage : Page, Autodesk.Revit.UI.IDockablePaneProvider ...
Yes, the project is a class library in the sense that it is a collection of classes, at least one of which extends IExternalApplication or IExternalCommand. Remember that you're not creating a standalone application, but adding functionality to an existing Windows application (Revit). Revit will instantiate the ThisApplication class and then call its .OnStartup() method when the Revit application starts. This shouldn't stop you from adding .xaml or .cs files to the project, though. I can do it using VS Community 2015 using Ctrl-Shift-A.
Hopefully this gets you started - I've been able to implement a WPF UI in Revit without any prior WPF experience, and I'm not even a real programmer, so it's definitely possible. Good Luck!
addendum
If you want to add WPF elements to an existing revit addin, you can follow the instructions here: How can I connect xaml and xaml.cs files
Ultimately I found it easier to migrate my addin code into a template made from a working sample, you may want to try this approach as well.
I've done .Net development for awhile but I'm new to the WPF technology. What is the supposed purpose of App.xaml? Also, what type of xaml code do you usually put in it? It seems like for simple applications it could be ignored and left untouched. Is this true?
App.xaml is the declarative portion of your code (usually generated by Visual Studio) extending System.Windows.Application. For example, Expression Blend can use App.xaml to share a Resource Dictionary or a design-time data set with your entire application. And, because we are using Microsoft products, whatever Expression Blend can do auto-magically, we can do by hand in Visual Studio.
Now the tangent: To me, to ask about the purpose of App.xaml is to ask about the purpose for System.Windows.Application. Feel free to accuse me of changing the original question (let the digital brutality ensue).
You can’t just open a System.Windows.Controls.Window in any Assembly you like… Chris Sells is likely telling me this in his book. I began to understand the purpose of System.Windows.Application while using MEF and MVVM Light to display WPF windows in DLLs (not EXEs). I got errors like this:
The type 'System.Windows.Markup.IComponentConnector' is defined in an assembly that is not referenced.
or
The type 'System.Windows.Markup.IQueryAmbient' is defined in an assembly that is not referenced.
The above error is simply saying that I’m trying to open a WPF Window inside of a DLL and not an EXE. Then, there’s this error:
The component 'Songhay.Wpf.WordWalkingStick.Views.ClientView' does not have a resource identified by the URI '/Songhay.Wpf.WordWalkingStick;component/views/clientview.xaml'.
This boils down to the absence of a facility that associates WPF Window XAML with the WPF “code” (an instance). This facility is associated with WPF EXEs and not WPF DLLs. Visual Studio auto-generates a WPF EXE class called App.g.cs (in your \obj\Debug folder) with this call in it: System.Windows.Application.LoadComponent(this, resourceLocater) where resourceLocater is a badly named variable containing a System.Uri pointing to the XAML like ClientView.xaml mentioned above.
I’m sure Chris Sells has a whole chapter written on how WPF depends on System.Windows.Application for its very life. It is my loss (quite literally of time) for not having read about it.
I have shown myself a little something with this unit test:
[STAThread]
[TestMethod]
public void ShouldOpenWindow()
{
Application app = new Application();
app.Run(new Window());
}
Failing to wrap a new Window in the System.Windows.Application.Run() method will throw an error from the land of COM talking about, “Why did you pull the rug from underneath me?”
For simple applications, it is true, it can be ignored. The major purpose for App.xaml is for holding resources (style, pens, brushes, etc.) that would would like to be available through out all of the windows in your application.
It is true. App.Xaml is some sort of central starting point. You CAN use it, or you CAN start your first window (it is defined in the app.xaml) manually. There are some lifetime events there centralls (like application start).
Storing resources that are used across the whole application.
Application is the root of the logical tree.
It is like Global.asax if you are coming from an ASP.NET background. You can also use it to share resources throughout your application. Comes in pretty handy for resource sharing.
App.xaml is a major part of wpf application.
It contains major four attributes
1.X:Class->used to connect you xaml and code-behind file(xaml.cs).
2.xmlns->To resolve wpf elements like canvas,stack panel(default one).
3.xmlns:x->To resolve XAML language definition.
4. StartupUri->To give start window when application is launching.
++++++++
App.xaml is the declarative starting point of your application. Visual
Studio will automatically create it for you when you start a new WPF
application, including a Code-behind file called App.xaml.cs. They
work much like for a Window, where the two files are partial classes,
working together to allow you to work in both markup (XAML) and
Code-behind.
App.xaml.cs extends the Application class, which is a central class in
a WPF Windows application. .NET will go to this class for starting
instructions and then start the desired Window or Page from there.
This is also the place to subscribe to important application events,
like application start, unhandled exceptions and so on.
One of the most commonly used features of the App.xaml file is to
define global resources that may be used and accessed from all over an
application, for instance global styles.
+++++++++
Source : http://www.wpf-tutorial.com/wpf-application/working-with-app-xaml/
Here is an updated answer in case people are still looking.
There is this excellent article on WPF, and the link specifically puts you at the App.Xaml point to begin teaching you the things you can do with it.
WPF is easy for the first very simple app or two. However, due to the increased flexibility of the framework, you need these types of tutorials to help you understand what can be done from where (in the various application files).
https://www.wpf-tutorial.com/wpf-application/working-with-app-xaml/
Good luck.
I am trying to merge all the assemblies of an class library in a single .dll file.
I can merge all the assemblies using the Ilmerge but is that when I use the merged dll in a Silverlight application I am having trouble when a template is apply to my control and binding problems if I use a control that inherits with UserControl.
is there any solution to solve this problem?
The problem is that when the initial dlls are built the Xaml in the project is added as a resource in the dll. The code generated to load this xaml will look something like this:-
System.Windows.Application.LoadComponent(this, new System.Uri("/SilverlightLibrary1;component/MyControl.xaml", System.UriKind.Relative));
Note how the name of the dll forms part of the Uri need to fetch the xaml. I doubt IlMerge is able to spot that and fix it up. Hence once merged the Uris cannot be found.
A resolution for this is probably uglier than multiple references or simply creating another project that links all the code files involved.
Previously all application level resources in a project I am authoring were stored in App.xaml. Then I decided to migrate from VS 2008 to 2010 and that is where the trouble started.
After migrating, I tried to do a little testing using a testing window instead of the normal startup window. After changing the startup object, suddenly I was faced with lots of compile errors and what not which (long story short) resulted in finding that there was now two files which held application level resources associated with the project: App.xaml (the original), and Application.xaml (at this time veritably empty). I migrated all of the resources (as well as merged dictionaries) over to the Application.xaml, and all was again right with the world so far as Visual Studio was concerned.
I then found out that Blend still wanted to use the App.xaml. I had created several resources and placed them in the Application.xaml, and saw that they were not being used when I compiled with Blend (but they were being used when I compiled with VS).
Where does one specify which XAML is the top level WPF resource file? This is getting out of hand...
There are slight differences in naming depending on what programming language you choose.
Visual Basic WPF projects use Application.xaml, while C# projects name it App.xaml.
As you probably know all .NET apps need a Main method. Also, windows apps need a message pump to get hooked to the Windows messaging system. IN WPF you can use the Application class to start listening to the windows messages.
Here's how you can do it explicitly.
VB
Public Class Startup
<STAThread()>
Shared Sub Main()
Dim app As New Application()
Dim window As New MainWindow()
window.Show()
app.Run()
End Sub
End Class
C#
public class Startup
{
[STAThread()]
public static void Main()
{
Application app = new Application();
MainWindow window = new MainWindow();
window.Show();
app.Run();
}
}
Since creating this type of code is common for WPF applications you can tell MSBuild to write this code by defining a XAML file and class that derives from System.Windows.Application and specifing its build action as 'ApplicationDefinition'.
In your situation, instead of editing the VbProj file, you could just select the correct file in Solution Explorer and change the BuildAction.
I have a custom WPF UserControl in a DLL file. I access the UserControl from PowerBuilder via OleObject (COM). I'm trying to create an instance of the UserControl (code in .NET dll).
Everything works fine when I'm using it via COM from C++, but in PowerBuilder, I'm getting this error message:
Error Message
Can you help me to figure out, what the problem is?
Tell me, if you need some more information.
Thank you so much!!
Found the solution. :)
Had to load the assembly WPFToolkit.dll and System.Windows.Controls.DataVisualization.Toolkit.dll manually via Assembly.LoadFrom("...");
Now it works!
I think you will have to load all assemblies which contain custom classes which are used in the xaml this way.