Create A WPF ObservableCollection From A SubSonic 2.2 Collection - wpf

If I have a DAL created by SubSonic 2.2, how do I convert the Collections created by it to WPF ObservableCollections in code (pref.VB.NET) to be consumed by WPF?

Sorry !VB:
[Test]
public void Exec_Testing()
{
ProductCollection products =
DB.Select().From("Products")
.Where("categoryID").IsEqualTo(5)
.And("productid").IsGreaterThan(50)
.ExecuteAsCollection<ProductCollection>();
Assert.IsTrue(products.Count == 77);
ObservableCollection<Product> obsProducts = new ObservableCollection<Product>(products);
}

You would have to manually add this to your DAL classes, but it's not too hard. In the top of each data access layer class, add "Implements INotifyPropertyChanged" and then in each property, add the code in the "set" like you see below.
Private _Book As String
Public Property Book() As String
Get
Return _Book
End Get
Set(ByVal value As String)
If Not _Book = value Then
_Book = value
' Raise the property changed event.
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Book"))
End If
End Set
End Property
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Related

ListView with grouping and sorting not refresh while INotifyPropertyChanged used

I have my own class which uses INotifyPropertyChanged correctly (Raising updates events), but when a property of type DateTime updated and called (View.Run) the listView not updating untill another property changing (not this property)
Now with the code:
Public Class EntryInfo
Implements INotifyPropertyChanged
ReadOnly Property DateAccessed As Date
Get
.......
Return _Access
End Get
End Property
Readonly Property Property1 as object
Get
.......
Return _Property1
End Get
End Property
Friend Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
RaiseEvent ApropertyHasChanged()
End Sub
Then when I need to Change the "DateAccessProperty" I use this code:
Friend Sub SetAccessTime(Dt As Date)
_Access = Dt
NotifyPropertyChanged("DateAccessed")
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''
After this I have a ListView named "LV1"
Dim Coll as new observableCollection(Of EntryInfo)
....... filing "Coll" with items (EntryInfo)
Lv1.ItemsSource =Coll
Then I do the following:
Do some sort and group operations.
Changing "DateAccessed" value. so that the "ApropertyHasChanged" event fired and at this point I used the following code
Private Sub RefreshViewNow()
Dim _view As ListCollectionView = TryCast(CollectionViewSource.GetDefaultView(LV1.ItemsSource), ListCollectionView)
If _view IsNot Nothing Then _view.Refresh()
'\\\ Items.Refresh()
End Sub
But _view not refreshed.
But if the property "Property1" changed the _View refreshed.
Any help?
The solution is by set the following "_view" properties:
_view.IsLiveFiltering = True
_view.IsLiveGrouping = True
_view.IsLiveSorting = True
or at least one of them if you want one of them only to be activated.

Correctly bind object instance property to a Label in code

This is supposed to be easy, yet I can't get it to work.
This is a simplified example so I can illustrate my problem. I have a List(Of Object) and I want to bind the Content of a Label to some property of an object in the list. I want to do this in code (Because those labels will be generated in runtime).
I create my object that will hold the value for the label and the list, that will hold those objects:
' The List to hold objects
Public Class BList
Public Shared listy As New List(Of BindTest)
End Class
' Object to hold label text
Public Class BindTest
Public Property Namy As String
End Class
Then I try to create the object and add it to the list. And try to set the binding for the label (for sake of simplicity, lets say I want bind to the first list item).
Dim bb As New BindTest
bb.Namy = "FirstName"
BList.listy.Add(bb)
B_label.SetBinding(Label.ContentProperty, "Namy")
B_label.DataContext = BList.listy.Item(0)
So far it works fine and label shows "FirstName" as expected. But then if I try to change the value of that first item like this:
BList.listy.Item(0).Namy = "Something else"
nothing happens and the label is not updated.
Thanks to Mike Eason.
I needed to implement INotifyPropertyChanged. I somehow thought, that it would be implemented automatically with all that WPF default-way of databinding everything. Oh well, one needs implement this manually.
So for the code to work, this part:
' Object to hold label text
Public Class BindTest
Public Property Namy As String
End Class
..must be changed to this:
' Object to hold label text
Public Class BindTest
Implements INotifyPropertyChanged
Private _Namy As String
Public Property Namy
Set(value)
_Namy = value
_PropertyChanged("Namy")
End Set
Get
Return _Namy
End Get
End Property
Private Sub _PropertyChanged(Optional ByVal PropertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropertyName))
End Sub
Private Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
End Class

MEF and PlugIn properties updates

I'm new to MEF and started a project to test it. What I'm trying to do is opening a MainForm that would load plugins based on an Interface. Those plugins need to be able to exchange information between them and the MainForm should be able to communicate with all of them too. So I started by creating my MainForm that loads a plugin. The plugin is only a form containing a ListBox. On the MainForm I have a button. I want that button to send a List(of String) to the plugin and that plugin to load that List(of String) in the ListBox. Currently, when I click on the MainForm button, it sends the list to the plugin. But the list is not loading in the plugin ListBox. Looking to find the problem, I added a new button on the MainForm to verify that the plugin property actually contains the list(of string) I sent it. And yes, the list contains all my strings. The problem needs to be that the ListBox isn't refreshing?
Part of the interface:
Public Interface IPlugIn
Property PlugInName as string
Property Files As List(Of String)
End Interface
Code in the MainForm Button:
Dim currentPlugIn As Contract.API.IPlugIn
currentPlugIn = PlugIns.Find(Function(x) x.PlugInName = "Test")
currentPlugIn.Files = IO.Directory.GetFiles("SomeFolder").ToList
Code in the PlugIn:
<Export(GetType(Contract.API.IPlugIn))> _
Public Class UserControl1
Implements System.ComponentModel.INotifyPropertyChanged, Contract.API.IPlugIn
Public Property Files As System.Collections.Generic.List(Of String) Implements
Contract.API.IPlugIn.Files
Get
If IsNothing(_files) Then
_files = New List(Of String)
End If
Return _files
End Get
Set(value As System.Collections.Generic.List(Of String))
_files = value
OnPropertyChanged("Files")
End Set
End Property
Public Event PropertyChanged(sender As Object, e As
System.ComponentModel.PropertyChangedEventArgs) Implements
System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New
ComponentModel.PropertyChangedEventArgs(propertyName))
End Sub
Code in PlugIn XAML:
<ListBox Name="lstFiles" ItemsSource="{Binding Path=Files}"/>
What's the problem? I searched the Internet for examples and found hundreds, but none of them is showing how to do what I want to do. Just before posting my question here, I added the INotifyPropertyChanged, it didn't resolved the problem. Would it be better for me to use PRISM, Caliburn.Micro or is MEF only going to be okay?
Thanks for your help!
Thanks everyone!
I finally found the answer.
I implemented PRISM EventAggregator and did change the following
In the Interface and PlugIns
Completely removed
Public ReadOnly Property PlugInUI As System.Windows.Controls.UserControl Implements
Contract.API.IPlugIn.PlugInUI
Get
Dim myUI As New UserControl1
Return myUI
End Get
End Property
In the Host
Changed
Public Sub OnImportsSatisfied() Implements
System.ComponentModel.Composition.IPartImportsSatisfiedNotification.OnImportsSatisfied
For Each plugInItem In WidgetList
Desktop.Children.Add(plugInItem.PlugInView)
Next
End Sub
to
Public Sub OnImportsSatisfied() Implements
System.ComponentModel.Composition.IPartImportsSatisfiedNotification.OnImportsSatisfied
For Each plugInItem In WidgetList
Desktop.Children.Add(plugInItem)
Next
End Sub
And now everything works as I wanted!
Athari, thanks for your comment.
I did fix the properties to ObservableCollection, but didn't fix the problem. Seems I'm missing something else.
Here's the full code.
Interface
Namespace API
Public Interface IPlugIn
Property Files As System.Collections.ObjectModel.ObservableCollection(Of String)
ReadOnly Property PlugInUI As System.Windows.Controls.UserControl
End Interface
End Namespace
PlugIn
Imports System.ComponentModel.Composition
<Export(GetType(Contract.API.IPlugIn))> _
Public Class UserControl1
Implements Contract.API.IPlugIn, System.ComponentModel.INotifyPropertyChanged,
System.Collections.Specialized.INotifyCollectionChanged
Private _files As System.Collections.ObjectModel.ObservableCollection(Of String)
Public Property Files As System.Collections.ObjectModel.ObservableCollection(Of String)
Implements Contract.API.IPlugIn.Files
Get
If IsNothing(_files) Then
_files = New System.Collections.ObjectModel.ObservableCollection(Of String)
End If
Return _files
End Get
Set(value As System.Collections.ObjectModel.ObservableCollection(Of String))
_files = value
OnPropertyChanged("Files")
OnCollectionChanged(New
Collections.Specialized.NotifyCollectionChangedEventArgs _
(Specialized.NotifyCollectionChangedAction.Reset))
End Set
End Property
Public ReadOnly Property PlugInUI As System.Windows.Controls.UserControl Implements
Contract.API.IPlugIn.PlugInUI
Get
Dim myUI As New UserControl1
Return myUI
End Get
End Property
Public Event PropertyChanged(sender As Object, e As
System.ComponentModel.PropertyChangedEventArgs) Implements
System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(Optional propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New
ComponentModel.PropertyChangedEventArgs(propertyName))
End Sub
Public Event CollectionChanged(sender As Object, e As
System.Collections.Specialized.NotifyCollectionChangedEventArgs) Implements
System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged
Public Sub OnCollectionChanged(args As
System.Collections.Specialized.NotifyCollectionChangedEventArgs)
RaiseEvent CollectionChanged(Me, args)
End Sub
End Class
PlugIn XAML
<Grid>
<ListBox Height="248" HorizontalAlignment="Left" Margin="30,31,0,0" Name="ListBox1"
VerticalAlignment="Top" Width="241" ItemsSource="{Binding Files}">
</Grid>
Host App
Imports System.ComponentModel.Composition
Imports System.ComponentModel.Composition.Hosting
Public Class HostApp
<ImportMany(GetType(Contract.API.IPlugIn))> _
Public Property PlugIns As List(Of Contract.API.IPlugIn)
Private _container As CompositionContainer
Public Sub Compose()
Dim catalog As New AggregateCatalog
catalog.Catalogs.Add(New DirectoryCatalog("pluginfolder"))
_container = New CompositionContainer(catalog)
_container.ComposeParts(Me)
End Sub
Public Sub LoadPlugIns()
Compose()
For Each item In PlugIns
Desktop.Children.Add(item.PlugInUI)
Next
End Sub
Private Sub HostApp_Loaded(sender As Object, e As System.Windows.RoutedEventArgs)
Handles Me.Loaded
LoadPlugIns()
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
Handles Button1.Click
Dim fileList As New Collections.ObjectModel.ObservableCollection(Of String)
For Each fileItem As String In IO.Directory.GetFiles("Somefolder")
fileList.Add(fileItem)
Next
PlugIns.Item(0).Files = fileList
End Sub
End Class
I need the Files property to be listed in the PlugIn ListBox.
Thanks again for your help!

VB.net WPF DataGrid ObservableCollection Binding property update

I am using VB.NET and WPF within Visual Studio 2010 Express.
Currently, I have:
A DataGrid by the name of downloadListDG. This has a column which is a template containing an image.
An ObservableCollection of a custom DownloadListItem class.
This DownloadListItem has a public property which is another custom class.
This class has a private dim which is a StateType (a custom enum), and a public readonly property which returns a string depending on what the StateType is (actually an image URI if you're curious).
The DownloadListItem also has a public property which just returns the StateType (this is just for binding purposes)
My problem is that whenever the StateType changes, the image column in the DataGrid does not change. I have been trying to use the IPropertyChangedNofity, but nothing changes, so either I'm using it incorrectly or I need to use another method.
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
AddHandler ControllerRef.StateChanged, AddressOf StateChangeHandler
Private Sub StateChangeHandler(NewState As State)
MsgBox(NewState)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("CurrentState"))
End Sub
Thanks in advance
Make sure the PropertyChanged event is notifying the UI of the property name you are bound to, not the property that triggers the change. Example:
Imports System.ComponentModel
Public Class DownloadListItem : Implements INotifyPropertyChanged
Friend Enum StateEnum
State1 = 0
State2 = 1
End Enum
Private _CurrentState As StateEnum
Private Sub ChangeEnumValue(NewValue As StateEnum)
_CurrentState = NewValue
OnPropertyChanged("ImageURI")
End Sub
Public ReadOnly Property ImageURI As String
Get
' TODO: Implement conditional logic to return proper value based on CurrentState Enum
End Get
End Property
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Protected Sub OnPropertyChanged(PropertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropertyName))
End Sub
End Class

Bind to my class with INotifyPropertyChanged

I am sorry if this question is double somewhere, I've searched but did not find.
I have created my own class.
Public Class MyListService
Implements INotifyPropertyChanged
Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Private Sub OnPropertyChanged(ByVal Title As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Title))
End Sub
Private _IsLoggedIn As Boolean = False
Public Property IsLoggedIn As Boolean
Get
Return _IsLoggedIn
End Get
Set(value As Boolean)
If _IsLoggedIn <> value Then
_IsLoggedIn = value
Call OnPropertyChanged("IsLoggedIn")
End If
End Set
End Property
End Class
In WPF project, I have in codebehind
Private WithEvents cWebService As new MyListService
In XAML:
<CheckBox IsChecked="{Binding IsLoggedIn}" x:Name="chkIsLoggedIn" />
Please can you tell me how to bind that "IsLoggedIn" property now to the Checkbox?
Regards
I have absolutely no VB experience but I've used WPF with C#.
Here is my guess:
you need to set DataContext of your CheckBox to point to the MyListService instance for the binding to work since the binding systems needs to know which object the IsLoggedIn property belongs to.

Resources