VB.net WPF DataGrid ObservableCollection Binding property update - wpf

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

Related

Wpf MVVM UI do not update implementing modularity,eventaggregator

i'm currently experimenting wpf communication between two views of different modules using prism IEventAggregator. publishing module and subscribing module is working fine, for some reason i can't understand why the subscriber UI is not updating.i place a button to display a msgbox at the subscriber module just to be sure that it receives it and it does. and i think i properly implement the INotifyPropertyChanged.
if i place subscribe in subscriber view's code-behind it works as i want it to be....do i do it the wrong way? please correct me. thanks.
a separate class for module message passing. this class is from this post http://www.shujaat.net/2010/12/wpf-eventaggregator-in-prism-40-cal.html
Public Class SendServices
Public Shared Property SendMessage As EventAggregator
Shared Sub New()
SendMessage = New EventAggregator
End Sub
End Class
Publisher :
Public Class Module1ViewModel
Private _msgsend As String
Public WriteOnly Property MessageSend As String
Set(value As String)
_msgsend = value
End Set
End Property
Public Sub Send()
SendServices.SendMessage.GetEvent(Of SendStringEvent).Publish(New SendString With {.Name = _msgsend})
End Sub
End Class
Subscriber :
Public Class Module2ViewModel
Implements INotifyPropertyChanged
Private _receivedMSG As String
Public Property ReceivedMSG As String
Get
Return _receivedMSG
End Get
Set(value As String)
_receivedMSG = value
OnPropertyChanged("ReceivedMSG")
End Set
End Property
'Binded to subscriber View button using interactions
Public Sub Received()
MsgBox(ReceivedMSG)
End Sub
Private Sub ReceivedMessage(msg As SendString)
_receivedMSG = msg.Name
End Sub
Public Sub New()
SendServices.SendMessage.GetEvent(Of SendStringEvent)().Subscribe(AddressOf ReceivedMessage, ThreadOption.UIThread, False)
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Sub OnPropertyChanged(ByVal name As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub
End Class
Subscriber View code-behind
Public Class Module2View
Sub New()
InitializeComponent()
Me.DataContext = New Module2ViewModel
End Sub
End Class
and the binding part to display the message
<TextBox Height="23" HorizontalAlignment="Left" Margin="111,39,0,0" Name="TextBox1" VerticalAlignment="Top" Width="158" Text="{Binding Path=ReceviedMSG}"/>
You don't fire the OnPropertyChanged event because you are directly setting the field _receivedMSG in your handler which is bypassing the property setter which fires the event.
So you should use the property setter instead:
Private Sub ReceivedMessage(msg As SendString)
ReceivedMSG = msg.Name
End Sub

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.

In Silverlight, add custom property to a generated Linq class + manage events

I'm using Linq to SQL classes in my WCF. Those classes are returned from the WCF methods to the Silverlight. Now, I want to add a custom property on a the generated class (Silverlight side) and trigger a PropertyChangedEvent on that particular property, based on another PropertyChangedEvent from another property. To be clear, here's a piece of code that doesn't work :
Partial Public Class DataConnection
Public Sub New()
AddHandler Me.PropertyChanged, AddressOf _PropertyChanged
End Sub
Private Sub _PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
If e.PropertyName = "ConnectionType" Then
Me.RaisePropertyChanged("ConnectionTypeEnum")
End If
End Sub
Private _ConnectionTypeEnum As String
Public ReadOnly Property ConnectionTypeEnum() As String
Get
Select Case Me.ConnectionType
Return //Something based on ConnectionType //
End Select
End Get
End Property
End Class
The problem is that the code in New() is never executed, so I never know when the ConnectionType is changed, so I can't trigger the PropertyChanged on ConnectionTypeEnum. (this property is used a in One-Way binding so I need it)
Does anyone have a solution for this ?
Thanks
You can use OnDeserializedAttribute
<OnDeserializedAttribute()> _
Public Sub WhenDeserialized(context As StreamingContext)
AddHandler Me.PropertyChanged, AddressOf _PropertyChanged
End Sub

Layered INotifyPropertyChanged

I have a class that implements INotifyPropertyChanged for a property.
I have a control that is bound to that property.
I have another class that listens to the propertychanged event. In the event handler of that class I change the value of the property in code.
The problem I have is that I don't want to do any logic in the event handler for the next time it will fire due to the change of the property due to code.
However if the user changes the value of the property in the mean time (via async gui input) I still want the logic to fire. I also need to make sure that the control gets updated (this is twoway binding).
What is the best way to do this without this becoming a complete mess?
One way to accomplish this would be to refactor the setter on your property so that it called a method taking a parameter indicating whether or not to raise the event. Here is a simple code sample:
Imports System.ComponentModel
Public Class Class1
Implements INotifyPropertyChanged
Public Property MyData() As String
Get
Return _myData
End Get
Set(ByVal value As String)
SetMyData(value, True)
End Set
End Property
Private Sub SetMyData(ByVal value As String, ByVal triggerPropertyChanged As Boolean)
_myData = value
If triggerPropertyChanged Then
OnPropertyChanged("MyData")
End If
End Sub
Private _myData As String
Private Sub OnPropertyChanged(ByVal propertyName As String)
SetMyData("new value", False)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
Your question is a bit vague, but you can check to see if the value has actually changed to determine if you should do your logic.
It would be better if you include some code to be more specific in your question.

Create A WPF ObservableCollection From A SubSonic 2.2 Collection

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

Resources