Can anyone suggest what might be missing from the following code. I am getting nothing displayed on my WinForm.
I have looked at the following related posts on this topic but they haven't solved the issue for me.
How to use Prisim within an ElementHost
Problems with Prism hosted in a WinForm ElementHost
WinForm with ElementHost
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' WPF application instance
_wpfApplication = Application.Current()
If Application.Current Is Nothing Then
_wpfApplication = New Application()
End If
' Load the application modules
Dim unityBootstrapper As New Bootstrapper()
unityBootstrapper.Run()
' Bind the shell to the ElementHost
Dim shellElement = unityBootstrapper.Container.Resolve(Of Shell)()
ehMaster.Child = shellElement
End Sub
Bootstrapper
Public NotInheritable Class Bootstrapper
Inherits UnityBootstrapper
Protected Overrides Function CreateShell() As DependencyObject
Return New Shell
End Function
Protected Overrides Function GetModuleCatalog() As IModuleCatalog
Dim catalog As ModuleCatalog = New ConfigurationModuleCatalog()
catalog.AddModule(GetType(Pitchbook.Excel.ChartWizardModule))
Return catalog
End Function
End Class
Shell
<UserControl x:Class="Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.codeplex.com/CompositeWPF">
<DockPanel>
<ItemsControl x:Name="HeaderRegion" cal:RegionManager.RegionName="HeaderRegion" DockPanel.Dock="Top" Height="auto">
</ItemsControl>
<ItemsControl x:Name="LeftRegion" cal:RegionManager.RegionName="LeftRegion" Width="auto" DockPanel.Dock="Left">
</ItemsControl>
<ItemsControl x:Name="MainRegion" cal:RegionManager.RegionName="MainRegion" DockPanel.Dock="Bottom">
</ItemsControl>
</DockPanel>
</UserControl>
Partial Public Class Shell
Inherits UserControl
Public Sub New()
InitializeComponent()
End Sub
End Class
ChartWizardModule
Public NotInheritable Class ChartWizardModule
Implements IModule
Private ReadOnly regionManager As IRegionManager
Public Sub Initialize() Implements IModule.Initialize
regionManager.RegisterViewWithRegion("MainRegion", GetType(Test))
End Sub
Public Sub New(regionManager As IRegionManager)
Me.regionManager = regionManager
End Sub
End Class
I didn't pay enough attention to this post
How to use Prisim within an ElementHost
The issue is that you need an Application.Current that is not null and is not equal to typeof(Application).
Therefore I created the following class
Public Class WpfApplicationAdapter
Inherits Windows.Application
' HACK - This class shouldn't be required. Look out for a resolution to this in future WPF versions.
End Class
And changed my WinForm constructor to the following
Public Sub New()
' This call is required by the designer.
InitializeComponent()
If Application.Current Is Nothing Then
Dim wpfAppAdapter As New WpfApplicationAdapter
End If
' Load the application modules
Dim formBootstrapper As New Bootstrapper
formBootstrapper.Run()
' Get the current instance of shell and bind it to the ElementHost
Dim shellElement = formBootstrapper.Container.Resolve(Of Shell)()
ehMaster.Child = shellElement
End Sub
Related
My project is in.NET 6. Why doesn't the following code work?
My understanding is to produce code through attributes, simplifying the coding.
Did I do something wrong?
Xaml:
<Window.DataContext>
<self:MainWindowVM />
</Window.DataContext>
<StackPanel >
<Label Content="{Binding Path=FirstLabel ,Mode=TwoWay ,UpdateSourceTrigger=PropertyChanged }" Height="50" />
<Button Command="{Binding Path=ExitMe}" Content="Exit" />
</StackPanel>
Codebedhing:
Imports CommunityToolkit.Mvvm.ComponentModel
Imports CommunityToolkit.Mvvm.Input
Class MainWindow
End Class
Partial Public Class MainWindowVM
Inherits ObservableObject
Public Sub New()
Me.FirstLabel = "default value..."
End Sub
<ObservableProperty>
Private FirstLabel As String
<RelayCommand>
Private Sub ExitMe()
Windows.Application.Current.Shutdown()
End Sub
End Class
At run-time I get two error messages:
ExitMe' property not found on 'object' ''MainWindowVM'
BindingExpression path error: 'FirstLabel' property not found on 'object' ''MainWindowVM'
I know the following code will work. But why doesn't the above code work?
Imports CommunityToolkit.Mvvm.ComponentModel
Imports CommunityToolkit.Mvvm.Input
Class MainWindow
End Class
Partial Public Class MainWindowVM
Inherits ObservableObject
Public Sub New()
Me.FirstLabel = "default value..."
Me.ExitMe = New RelayCommand(AddressOf exMe)
End Sub
<ObservableProperty>
Private fLabel As String
Public Property FirstLabel As String
Private Sub Save()
Me.fLabel = FirstLabel
End Sub
<RelayCommand>
Private Sub exMe()
Windows.Application.Current.Shutdown()
End Sub
Public ReadOnly Property ExitMe As ICommand
End Class
I am still learning how to use INotifyPropertyChanged. I was able to see it work with a non-persisted list in this post. I am now trying to use an SQL persisted list.
XAML. Some of the unused grid space was for comparisons to the non-persisted list, but not relevant to this post's question.
<StackPanel Grid.Column="0">
<Button Margin="25" Content="Insert an item" Click="InsertAnItem_Click"/>
</StackPanel>
<StackPanel Grid.Column="1">
<Button Margin="25" Content="Clear stored list" Click="ClearStoredList_Click"/>
<Label Content="{}{Binding MyList2}"/>
<ListBox Name="listBox3" ItemsSource="{Binding MyList2}" DisplayMemberPath="Name" Height="100">
</ListBox>
<Label Content="updated with MyList2 using code behind"/>
<ListBox Name="listBox4" DisplayMemberPath="Name" Height="100">
</ListBox>
</StackPanel>
CodeBehind
Partial Class MainWindow
Private vm = New ViewModel
Sub New()
InitializeComponent()
DataContext = vm
For Each item In vm.MyList2
listBox4.Items.Add(item)
Next
End Sub
Private Sub InsertAnItem_Click(sender As Object, e As RoutedEventArgs)
vm.InsertAnItem()
listBox4.Items.Clear()
For Each item In vm.MyList2
listBox4.Items.Add(item)
Next
End Sub
Private Sub ClearStoredList_Click(sender As Object, e As RoutedEventArgs)
vm.ClearStoredList()
End Sub
End Class
ViewModel
Public Class ViewModel
Implements INotifyPropertyChanged
Public Property dbList As New Mvvm2DbContext
Public Property MyList2 As New List(Of MyListItem)
Public Sub New()
MyList2 = dbList.SqlStoredList.ToList()
End Sub
Public Sub InsertAnItem()
Dim anItem As New MyListItem
anItem.Name = "Item " & MyList2.Count()
MyList2.Add(anItem)
dbList.SqlStoredList.Add(anItem)
dbList.SaveChanges()
NotifyPropertyChanged("MyList2")
End Sub
Public Sub ClearStoredList()
Using db = New Mvvm2DbContext
Dim allItems = db.SqlStoredList
Try
db.SqlStoredList.RemoveRange(allItems)
Catch ex As Exception
Dim s = ex.Message
MessageBox.Show(s)
End Try
db.SaveChanges()
End Using
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Public Sub NotifyPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End Class
Model
Public Class MyListItem
Public Property MyListItemID() As Integer
Get
Return _MyListItemID
End Get
Set(ByVal value As Integer)
_MyListItemID = value
End Set
End Property
Private _MyListItemID As Integer
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Private _Name As String
Public Property Desc() As String
Get
Return _Desc
End Get
Set(ByVal value As String)
_Desc = value
End Set
End Property
Private _Desc As String
End Class
dbContext
Public Class Mvvm2DbContext
Inherits DbContext
Public Sub New()
MyBase.New("name=MVVM2DbConnection")
End Sub
Public Property SqlStoredList As DbSet(Of MyListItem)
End Class
My line NotifyPropertyChanged("MyList2") in the ViewModel doesn't cause the bound list to update.
I think the MyList2 definition in the ViewModel must be incorrect, but I don't understand how to make it different if that's the problem.
What is the proper code to get changes to percolate to the display? As always, if there are best practices I'm missing, please advise.
Updated after initial post but questions still remain:
The following changes appear to cause INotifyPropertyChanged to now work in this code. I'm guessing INotifyPropertyChanged doesn't work unless a property is defined with specific get/set declarations.
ViewModel. The MyList2 definition is changed and New() is changed.
Public Property MyList2() As ObservableCollection(Of MyListItem)
Get
Return _MyList2
End Get
Set(ByVal value As ObservableCollection(Of MyListItem))
_MyList2 = value
End Set
End Property
Private _MyList2 As New ObservableCollection(Of MyListItem)
Public Sub New()
For Each item In dbList.SqlStoredList
MyList2.Add(item)
Next
End Sub
The reason I previously defined MyList2 as:
Public Property MyList2 As New List(Of MyListItem)
Was because in New() initializing MyList2 with this line wouldn't compile:
MyList2 = dbList.SqlStoredList.ToList()
Even if I tried a DirectCast, List(Of T) can't be converted to an ObservableCollection(Of T). I'm guessing that's because of all the 'plumbing' behind the scenes?
Anyway, INotifyPropertyChanged seems to work fine now. But, I would appreciate any instruction regarding mistakes I'm making implementing this simple persisted list with INotifyPropertyChanged.
However, the persisted list is not fully bound. MyList2 doesn't clear when the SQL database is cleared. It seems to me that there must be more to this because changes to the SQL database could be made by other processes, and I don't see how this code would know that.
What do I do to ensure all updates get reflected in the UI?
The problem with your code is that the property MyList2 is not changing...its contents are changing. So that is why the property notification on MyList2 does nothing...MyList2 is still MyList2.
What you need is a collection class that implements notification. ObservableCollection would fit this need. So if you simply replace List(Of MyListItem) with ObservableCollection(Of MyListItem) I think things will start working.
I have a simple Button user Control that I use to aggregate all button functionality within my code:
Partial Public Class CommandButton
Inherits UserControl
Implements INotifyPropertyChanged
Public ReadOnly ButtonCmdProperty As DependencyProperty = DependencyProperty.Register("ButtonCmd", GetType(ICommand), GetType(CommandButton), New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnButtonCmdChanged)))
Public ReadOnly ButtonTextProperty As DependencyProperty = DependencyProperty.Register("ButtonText", GetType(String), GetType(CommandButton), New PropertyMetadata("Undefined", New PropertyChangedCallback(AddressOf OnButtonTextChanged)))
Public Sub New()
InitializeComponent()
End Sub
#Region "ButtonCmd"
Public Property ButtonCmd As ICommand
Get
Return DirectCast(GetValue(ButtonCmdProperty), ICommand)
End Get
Set(value As ICommand)
SetValue(ButtonCmdProperty, value)
End Set
End Property
Private Sub OnButtonCmdChanged()
OnPropertyChanged("ButtonCmd")
End Sub
#End Region
#Region "ButtonText"
Public Property ButtonText() As String
Get
Return DirectCast(GetValue(ButtonTextProperty), String)
End Get
Set(value As String)
SetValue(ButtonTextProperty, value)
End Set
End Property
Private Sub OnButtonTextChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
OnPropertyChanged("ButtonText")
End Sub
#End Region
End Class
Here is an example of where I use it in XAML code:
<controls:CommandButton x:Name="btnEdit"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="100"
Grid.Column="0"
ButtonCmd="{Binding EditButton.ButtonCmd}"
ButtonText="{Binding EditButton.ButtonText, Mode=TwoWay}"
ButtonTooltip="{Binding EditButton.ButtonTooltip}"
IconHeight="{Binding EditButton.IconHeight}"
IconWidth="{Binding EditButton.IconWidth}"
IconSource="{Binding EditButton.IconSource}"
IsVisible="{Binding EditButton.IsVisible}"
ShowIcon="{Binding EditButton.ShowIcon}"
ShowText="{Binding EditButton.ShowText}" />
(As you can see there are many other properties, but I have omitted them for brevity sake.)
I have been working with the same code for over 2 years in VS2010 with no problems. Since upgrading to VS2013, every page where I use this button throws the error message:
Object of Type System.Windows.Data.BindingExpression cannot be converted to type System.String
on each binding. It doesn't appear to affect the way the user control works when running, but I can no longer see canvas when writing my XAML. (IE. the XAML won't render in the canvas area) I am pretty sure I have the dependency properties written correctly, but I thought I'd throw it out here to see if I am missing something or if there is a way to disable this error check.
Quick question about a windows service, I've added a setup project for my Windows service, and ive added a custom dialog to it, with 4 text fields, but my question is how to i get these informations/variables?
Ive also added an installer for the windows service also, and afterwards the setup project, with the custom dialog.
The informations is something like database connection strings, and so on - so just string values.
This is my code for the "project installer" . the installer item ive added for the windows serive if you wanted to see it.
Imports System
Imports System.ComponentModel
Imports System.Configuration.Install
Imports System.ServiceProcess
Imports System.Runtime.InteropServices
Public Class ProjectInstaller
Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeComponent()
My.Settings.TestSetting = Context.Parameters.Item("PathValue")
#If DEBUG Then
Dim ServicesToRun As ServiceBase()
ServicesToRun = New ServiceBase() {New tdsCheckService()}
ServiceBase.Run(ServicesToRun)
#Else
Dim listener As New tdsCheckService()
listener.Start()
#End If
End Sub
Public Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary)
MyBase.Install(stateSaver)
Dim regsrv As New RegistrationServices
regsrv.RegisterAssembly(MyBase.GetType().Assembly, AssemblyRegistrationFlags.SetCodeBase)
End Sub
Public Overrides Sub Uninstall(ByVal savedState As System.Collections.IDictionary)
MyBase.Uninstall(savedState)
Dim regsrv As New RegistrationServices
regsrv.UnregisterAssembly(MyBase.GetType().Assembly)
End Sub
Private Sub ServiceProcessInstaller1_AfterInstall(sender As Object, e As InstallEventArgs) Handles ServiceProcessInstaller1.AfterInstall
End Sub
Private Sub ServiceInstaller1_AfterInstall(sender As Object, e As InstallEventArgs) Handles ServiceInstaller1.AfterInstall
End Sub
End Class
You should eb able to access them using the Context object.
'Get Protected Configuration Provider name from custom action parameter
Dim variableName As String = Context.Parameters.Item("dialogSettingName")
Public Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary)
MyBase.Install(stateSaver)
I have created a wpf vb.net project and am trying to set a simple databing. I'm not quiet sure how to set my DataContext = this; in the codebind. Currently when i run the program my Label never is updated. I have included my code below. What I'm i missing?
<Window x:Class="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>
<Label Content="{Binding person.Name}"/>
</Grid>
</Window>
Class MainWindow
Private Property person As New Person()
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
person.Name = "Poco"
End Sub
End Class
System.ComponentModel
Public Class Person
Implements INotifyPropertyChanged
Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
OnPropertyChanged(New PropertyChangedEventArgs("Name"))
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)
If Not PropertyChangedEvent Is Nothing Then
RaiseEvent PropertyChanged(Me, e)
End If
End Sub
End Class
This is close - you need to name your label in the XAML (so that you can reference it from the code behind) and then specify the path within the bound object to the data you would like to bind. In this case you will be binding an object with a Name property whose content you would like to assign to the label text:
<Label Name="MyLabel" Content="{Binding Path = Name}"/>
and then in your code you need to set the DataContext of the label to the object you would like to have it bound to, in this case a specific instance, somePerson of the class Person :
Private somePerson As New Person
Public Sub New()
InitializeComponent()
MyLabel.DataContext = somePerson
somePerson.Name = "Poco"
End Sub