VB.NET: WPF Single Instance - wpf

Has anyone using VB.NET 2010 been able to create a single instance application?
I've followed the MSDN sample but it does not have an Application.xaml file.
Converting any C# samples to VB doesn't work as I cannot override the Main sub in Application.xaml (C# calls it App.xaml).

You can try using a Mutex. In the projects properties, disable the application framework and set Sub Main as the startup object. Then add a Module to your project:
Imports System.Threading
Module EntryPoint
Sub Main()
Dim noPreviousInstance As Boolean
Using m As New Mutex(True, "Some Unique Identifier String", noPreviousInstance)
If Not noPreviousInstance Then
MessageBox.Show("Application is already started!")
Else
Dim mainWindow As New MainWindow()
Dim app As New Application()
app.Run(mainWindow)
End If
End Using
End Sub
End Module
With this method, you will have to take care of your app's shutdown by calling the Shutdown method of the application.

Here's a few possible solutions. I'd look through the whole thread here before deciding on one. Make sure you backup your code before trying any of these, so if one doesn't work, you can try another.
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/6c15b837-9149-4b07-8a25-3266949621a7/

Related

Change connection EF at runtime in WPF app

I have a WPF app that I'd like to change the connection string programmatically when the app loads. I use the Database-First approach for EF.
I spent a lot of time implementing various solutions found online including stack overflow and can't seem to get it to work.
The most common way seems to be to modify the Entity partial class. When I do this I get the following error at runtime:
Additional information: The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715
I got the same error implementing various other ways as well. If someone could please help me implement a way to change the connection string at runtime I'd greatly appreciate it.
My current implementation is taken from this example solution:
Changing Databases at Run-time using Entity Framework
Implementation:
App.config containts the connection string and name
Partial class added with same name as Entity class:
Imports System.Data.Entity
Imports System.Data.EntityClient
Imports System.Data.SqlClient
Partial Public Class MyEntityName
Inherits DbContext
Public Sub New(ByVal connString As String)
MyBase.New(connString)
End Sub
End Class
In my Application.xaml code file I set a global string variable by calling a method that builds the EntityConnectionStringBuilder. This global string variable is then passed into an entity constructor.
Imports System.Reflection
Imports DevExpress.Xpf.Core
Imports System.Data.EntityClient
Class Application
Public Sub New()
entityConnStr = BuildConnectionString("[MyDataSource]", "[MyDatabase]")
End Sub
Private Function BuildConnectionString(ByVal DataSource As String, ByVal Database As String) As String
' Build the connection string from the provided datasource and database
Dim connString As String = "data source=" & DataSource & ";initial catalog=" & Database & ";persist security info=True;user id=[user];password=[password];trustservercertificate=True;MultipleActiveResultSets=True;App=EntityFramework""
' Build the MetaData... feel free to copy/paste it from the connection string in the config file.
Dim esb As New EntityConnectionStringBuilder()
esb.Metadata = "res://*/DB.[MyEntityName].csdl|res://*/DB.[MyEntityName].ssdl|res://*/DB.[MyEntityName].msl"
esb.Provider = "System.Data.SqlClient"
esb.ProviderConnectionString = connString
' Generate the full string and return it
Return esb.ToString()
End Function
Usage:
Using context = New MyEntity("entityConnStr")
Public connection variable string:
Public entityConnStr As String
I think you should remove the quotes when you pass the connection string to the constructor. You want to use the variable contents, not the variable name.
Use this:
Using context = New MyEntity(entityConnStr)
Instead of this:
Using context = New MyEntity("entityConnStr")

Querying Access database vb.net

I am trying to figure out how to query an access database to take info from the database and put it into a class array. I know how to do some querying using basic LINQ, but not sure how to do it the way I want it to. I have a character class I am using, I am storing all the character traits in a database. I want to query the database and add that info to a class array. Any help would be greatly appreciated.
Here at the class private variables which are the same traits in the database:
Public Class Character
Private _strName As String
Private _intLevel As Integer
Private _intHealth As Integer
Private _intDamage As Integer
Private _intScore As Integer
First of all. I have to say this is not a good question.
Actually what you are saying is...: Please build me the dataconnections for this acces database and a visual studio form.
But because I'm in a good mood, That's what I did for you.
I created a little database file in acces.I saved it into a folder called database. Which is located in the project directory.
I made 2 classes. 1 CharactersForm, and 2 Gateway
the gateway is to make an connection to your Acces database.
The CharactersForm is the form what you see when you debug
Here is the CharactersForm class.
Make sure you drag and drop a listbox and a button
Call the listbox ListBoxCharacters.
Call the button InladenButton. Or call it whatever you want, But make sure it will fit the code given.
Option Explicit On
Option Strict On
Option Infer On
Public Class CharactersForm
Dim _CharactersGateway As New Gateway
Private Sub InladenButton_Click(sender As Object, e As EventArgs) Handles InladenButton.Click
_CharactersGateway.LoadDataTableCharacters()
ListBoxCharacters.DataSource = _CharactersGateway.CharactersDataTable
ListBoxCharacters.DisplayMember = "Name"
End Sub
End Class
The Gateway Class ( to make connection to your acces file)
If somehow visual studio cannot reach the database then it means the connectionstring is not correct. Make sure the connection string is exactly as where your accesfile.accdb is located
Option Explicit On
Option Strict On
Option Infer On
Imports System.IO
Imports System.Data.OleDb
Public Class Gateway
Public Shared AppPath As String = Application.StartupPath()
'\Debug
Public Shared DirectoryUp1 As String = Path.GetDirectoryName(AppPath)
'\bin
Public Shared DirectoryUp2 As String = Path.GetDirectoryName(DirectoryUp1)
'\CharactersStackOverFlow
Public Shared DirectoryUp3 As String = Path.GetDirectoryName(DirectoryUp2)
'\CharactersStackOverFlow
Public Shared AccesDatabaseFilePath As String = DirectoryUp3 & "\DataBase\Characters.accdb"
Dim ConnectionString As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " & AccesDatabaseFilePath)
Public Property DataSetCharacters As New DataSet
Public ReadOnly Property CharactersDataTable As DataTable
Get
CharactersDataTable = DataSetCharacters.Tables("Characters")
End Get
End Property
Public CharactersDataAdapter As OleDbDataAdapter
Public Sub LoadDataTableCharacters()
CharactersDataAdapter = New OleDbDataAdapter("SELECT * FROM Characters", ConnectionString)
CharactersDataAdapter.Fill(DataSetCharacters, "Characters")
Dim kamersCommandBuilder As New OleDbCommandBuilder(CharactersDataAdapter)
End Sub
End Class
This is as Yuriy Galanter said. You need the OleDbConnection.
If you are using office 2010 and you get thsi warning ::
'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine
You need to download the 2007 Office System Driver. It works also for 2010 don't ask me why.
Type '2007 Office System Driver' in google. And from microsoft you can download and install it.
ALL DONE!
if you run the program and press the load button. The names of your characters will come in the listbox.
If you want to put values of the fields of the database in variables. Then it's just about making a for loop and put them in dimmed variables. That is something I'm sure you can do yourself. The connection to the database and the loading in the program is already sorted out now!
Good luck
Jonathan

Command Parameter with RelayCommand

I'm using a version of the common RelayCommand class and trying to pass a command parameter but not having success. I get the following error:
Error 29 Method 'Private Sub KeyPadPressExecute(param As Object)' does not have a signature compatible with delegate 'Delegate Sub Action()'.
I've looked at the many examples of using parameters with commands, but I can't make sense out of them. I don't understand where I'm supposed to get the parameter from that will be passed on to KeyPadPressExecute().
Here's the relevant code:
Private Sub KeyPadPressExecute(param As Object)
Debug.Print(param.ToString)
End Sub
Private Function CanKeyPadPressExecute() As Boolean
Return True
End Function
Public ReadOnly Property KeyPadPress() As ICommand
Get 'Error occurs on next line
Return New RelayCommand(AddressOf KeyPadPressExecute, AddressOf CanKeyPadPressExecute)
End Get
End Property
What my XAML looks like:
<Button Command="{Binding KeyPadPress}" CommandParameter="1" Width="84"></Button>
I'm using VS 2012 and targeting .NET 4.5.
Note: My original post said I was using MicroMVVM. Closer inspect of the project indicates that the assembly named MicroMVVM is not related to the MicroMVVM framework hosted at codeplex. This project was started by someone else, thus the confusion.
From a RelayCommand implementation seen at GitHub, one can tell that the class effectively hides and swallows the command parameter. Perhaps you should try to use the generic version of the class instead: RelayCommand(Of T). The run-time exception is pretty clear: there's a mismatch between the MicroMVVM class's constructor, taking only a blunt Sub Action() delegate; and your command's execute handler, taking an object argument.
NB: Please forgive my bad VB, it's not my mother tongue.
Update: I see that MicroMVVM is hosted at CodePlex, but there's no RelayCommand class in there (apparently replaced by the smarter DelegateCommand class). The link to the probably unrelated project at GitHub still serves its purpose as an example and source of information. Comments are welcome.

Loading dependencies in Unity Container in WinForms application

This is how the solution partially looks like.
Since I am using the Onion Architecture in a Winforms environment, hence I have the UI, Infrastructure and Core layers. All the layers are loosely coupled using Dependency Injection. What I want to achieve is that whenever a form from e.g. Accounts Forms (Class Library) is loaded, all the dependencies for that should be loaded in the UnityContainer i.e. types registered. These dependencies are interfaces and implementations present in Core and Infrastructure projects.
My confusion is that where should I write the code to register dependencies? What would be the Composition Root for this application? Please note that forms from e.g. Accounts Forms, HR Forms, etc are all loaded using reflection in the Main Windows application which references only the Base Forms Project.
After Eben Roux's suggestions
Here is how I am executing the wireup code when the assembly is loaded:
Dim assemb As System.Reflection.Assembly
...
...
If assemb IsNot Nothing Then
Dim type As Type = GetType(IDependencyWiring)
Dim modules As List(Of Type) = assemb.GetTypes().Where(Function(p) type.IsAssignableFrom(p) AndAlso p.IsClass).ToList()
For Each [module] As Type In modules
Dim argTypes As Type() = New Type() {}
Dim cInfo As ConstructorInfo = [module].GetConstructor(argTypes)
Dim dependencyWiringModule As IDependencyWiring = DirectCast(cInfo.Invoke(Nothing), IDependencyWiring)
dependencyWiringModule.WireUp()
Next
End If
Here's is the Module having the WireUp method:
Public Class AccountModule : Implements IDependencyWiring
Private Shared Container As IUnityContainer
Public Sub New()
Container = New UnityContainer()
End Sub
Public Sub WireUp() Implements IDependencyWiring.WireUp
Container.RegisterType(Of IInterface1, Class1)()
Container.RegisterType(Of IInterface2, Class2)()
Container.RegisterType(Of IInterface3, Class3)()
Container.RegisterType(Of IInterface4, Class4)()
End Sub
Public Shared Function Resolve(typeToResolve As Type) As Object
Return Container.Resolve(typeToResolve.GetType())()
End Function
End Class
So my questions now are:
Is it the right approach to store the Container as Shared and use it to resolve dependencies via Resolve method?
There is a problem in the way I am encapsulating the Resolve behavior of the Container. What would be the right syntax for that? I don't want to reference Unity on each of the form to be able to call the Resolve method, so I am encapsulating that i my own Resolve method. In this way I could easily replace the AccountModule with another one if I want to change the IOC Container without having the change the container references everywhere.
With this type of plug-in architecture you effectively end up with more than one composition root (of sorts). There will in all probability be some dependencies only your plug-in knows about and can wire up.
So part of your architecture should be the loading of the plug-ins. This probably happens somewhere in the main application in the wire-up bit (composition root) which would then give each plug-in the opportunity to perform its wiring.
Since not all plug-ins may need wiring one could make that explicit by using a seperate interface:
public interface IDependencyWiring
{
public void WireUp(IDependencyContainer container); // <-- changed to conform to update
}
And then in the main composition root:
foreach (var plugin in plugins)
{
var wiring = plugin as IDependencyWiring;
if (wiring != null)
{
wiring.WireUp(myContainer);
}
}
I hope that makes sense.
Update:
Firstly I would use a safe cast. TryCast in the VB.NET world. You could use dependency iversion to get rid of Unity from the actual plug-ins by using your own interface. Something like so:
public interface IDependencyContainer
{
void Register(Type type);
void Register<T>();
void Resolve(Type type);
void Resolve<T>();
}
Well, you would add what you need. Then pass in the reference to the container in the wire-up as I did up top public void WireUp(IContainer container);.
The Resolve behahiour is somewhat problematic in that you seem to be headed in a Service Locator direction. Try to get as much of the resolving done by the container by using constructor (or other) injection. Of course this works fine for Singleton components. For the Transient ones I'd rather use a Singleton factory that receives an instance of the IDependencyContainer (so that will also be registered), and it does the resolving (creation, really) for you.

How to use another ioc container with mef?

i am using mef with prism. i can use mef because i like the export, import, metadata attributes and mostly aggregate cagalog usage. so i want to use mef with prism project.
In my plan, my solution projects must be use autofac or castle windsor ioc container and i implement like that except prism project(wpf). In case, i am not prefer to use autofac or castle windsor instead of mef's default di/ioc but too many alternative usage of personal experimantals are failed.
Is there a any stable sample project i can use? I want to change only ioc of mef with all mef functionalty.
My classic mef bootstrapper code is bellow
Imports System.ComponentModel.Composition.Hosting
Imports Microsoft.Practices.Prism.MefExtensions
Imports Microsoft.Practices.ServiceLocation
Public Class Bootstrapper2
Inherits MefBootstrapper
Protected Overrides Sub ConfigureContainer()
MyBase.ConfigureContainer()
Dim ag As New AggregateCatalog()
ag.Catalogs.Add(New AssemblyCatalog(GetType(Bootstrapper2).Assembly))
ag.Catalogs.Add(New DirectoryCatalog("..\..\modules\", "Prism.Sample.Modules.*.dll"))
Me.AggregateCatalog.Catalogs.Add(ag)
End Sub
Protected Overrides Function CreateShell() As DependencyObject
Dim s As Shell = ServiceLocator.Current.GetInstance(Of Shell)()
Return s
End Function
Protected Overrides Sub InitializeShell()
Application.Current.MainWindow = Shell()
Application.Current.MainWindow.Show()
End Sub
End Class
Shell's code is bellow:
Imports System.ComponentModel.Composition
<Export()> _
Public Class Shell
Sub New()
InitializeComponent()
End Sub
<Import(AllowRecomposition:=False)> _
Public Property ViewModel() As ShellViewModel
Get
Return CType(Me.DataContext, ShellViewModel)
End Get
Set(value As ShellViewModel)
Me.DataContext = value
End Set
End Property
End Class
Now, everythings working like an expected.
modified/overrided bootstrapper's ConfigureServiceLocator() method is bellow.
Private autofacBuilder As New Autofac.ContainerBuilder
Protected Overrides Sub ConfigureServiceLocator()
Dim autofacContainer = autofacBuilder.Build()
Dim autofacSL = New Prism.AutofacExtension.AutofacServiceLocatorAdapter(autofacContainer)
ServiceLocator.SetLocatorProvider(Function() autofacSL)
End Sub
then i have got an too many resolving exception for example:
exception message:
Activation error occured while trying to get instance of type RegionAdapterMappings, key "".
Prism or another code base trying to resolve IRegionAdapterMappings from the servicelocator but currentservice locator not knowns what is this.Because mef is allready registered this types((ConfigureContainer) before CreateServiceLocator.
So, then i trying to add mef's aggregate catalog to register autofac container with Autofac.Integration.Mef project like this:
Private autofacBuilder As New Autofac.ContainerBuilder
Protected Overrides Sub ConfigureServiceLocator()
autofacBuilder.RegisterComposablePartCatalog(Me.AggregateCatalog)
Dim autofacContainer = autofacBuilder.Build()
Dim autofacSL = New Prism.AutofacExtension.AutofacServiceLocatorAdapter(autofacContainer)
ServiceLocator.SetLocatorProvider(Function() autofacSL)
End Sub
Then i have got a diffrent exception: IServiceLocator not registered etc...
I have not a complately solutions for changing mef's ioc container because its own container types and uses her own extensibility. Tried to use Autofac.Integration.Mef but maybe it not future compatible. maybe not developep when mef' new releases.
I am a big blakc hole i think. Is there a any way can't i see?
Thanks.

Resources