Binding and Async Operations - wpf

I have created a Window with a TextBlock inside. I have bound the Text property and everything works fine.
BUT
When I change the bounded property while inside a Task then nothing works!!
Do you know why?
Public Async Sub StartProgress()
Try
LoadingText = "text 1" 'Works perfect
Dim fResult As Boolean = Await LoadModules()
If Not fResult Then
MessageBox.Show(Me.Error)
End If
m_oView.Close()
Catch ex As Exception
Msg_Err(ex)
End Try
End Sub
Public Async Function LoadModules() As Task(Of Boolean)
Try
Await Task.Delay(3000)
LoadingText = "text 2" 'Nothing Happens
Await Task.Delay(5000)
LoadingText = "complete" 'Nothing Happens
Await Task.Delay(3000)
Return True
Catch ex As Exception
Me.Error = ex.Message
Return False
End Try
End Function
text 2 and 3 are never shown. If I change dynamically the Text of the textblcok(ex : m_oView.txtLoadingText.Text) It works fine(but it's mnot a solution)
EDIT
This is the ViewModel Base, every ViewModel implements that Class.
Public Class VM_Base
Implements IDisposable
Implements INotifyPropertyChanged
Private m_oDS As MxDataSet
Public Property [Error] As String
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Protected Sub New()
m_oDS = New MxDataSet
End Sub
Protected Overrides Sub Finalize()
Try
Me.Dispose(False)
Debug.Fail("Dispose not called on ViewModel class.")
Finally
MyBase.Finalize()
End Try
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Me.Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(disposing As Boolean)
End Sub
Protected Overridable Sub OnPropertyChanged(propertyName As String)
Me.EnsureProperty(propertyName)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
<Conditional("DEBUG")> _
Private Sub EnsureProperty(propertyName As String)
If TypeDescriptor.GetProperties(Me)(propertyName) Is Nothing Then
Throw New ArgumentException("Property does not exist.", "propertyName")
End If
End Sub
End Class
How StartProgress is Called:
<i:Interaction.Triggers>
<i:EventTrigger EventName="ContentRendered">
<i:InvokeCommandAction Command="{Binding DataContext.WindowsActivatedCommand,ElementName=fLoading}" />
</i:EventTrigger>
</i:Interaction.Triggers>
EDIT
Binding TextBlock to Property
Public Property LoadingText As String
Get
Return m_sLoadingText
End Get
Set(value As String)
m_sLoadingText = value
OnPropertyChanged("LoadingText")
End Set
End Property
<TextBlock x:Name="txtLoading" Width="450"
Grid.Row="1" VerticalAlignment="Center"
HorizontalAlignment="Left"
TextWrapping="Wrap" Text="{Binding LoadingText}">
</TextBlock>

Here's a detailed answer on what you need to do to make sure calls that originate on non-UI threads invoke UI methods properly:
Ensuring that things run on the UI thread in WPF

You need to implement INotifyPropertyChanged on your view model type, and have the LoadingText setter raise that event.

# Manolis Xountasis,
I do not know VB.net, but I test code in C#, it is ok. Below is my code:
public partial class MainWindow : Window
{
private TestViewModel _tvm = new TestViewModel();
public MainWindow()
{
InitializeComponent();
this.wndTest.DataContext = _tvm;
_tvm.TestData = "First Data";
this.btnAsync.Click += BtnAsyncOnClick;
}
private void BtnAsyncOnClick(object sender, RoutedEventArgs routedEventArgs)
{
var task = Task.Factory.StartNew(() => this.Dispatcher.Invoke(new Action(() => _tvm.TestData = "changed data")));
}
}
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication3" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="WpfApplication3.MainWindow"
x:Name="wndTest"
Title="MainWindow"
Height="350"
Width="525">
<!--<Window.Resources>
<local:TestViewModel x:Key="TestViewModelDataSource" d:IsDataSource="True"/>
</Window.Resources>
<Window.DataContext>
<Binding Mode="OneWay" Source="{StaticResource TestViewModelDataSource}"/>
</Window.DataContext>-->
<Grid>
<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding TestData}" />
<Button x:Name="btnAsync" Content="Change Async" HorizontalAlignment="Right" VerticalAlignment="Top"/>
</Grid>
Hope this code is useful for you.

According to this page (emphasis mine):
Now this might scare you off the C# asynchronous language features,
because it makes them seem slow, but this is not a fair test. The
reason this takes so much longer is that we’ve given the program much
more work to do. When the simple, synchronous version runs on the UI
thread, WPF does very little immediate work for each item we add to
the LogUris collection. Data binding will detect the change—we’ve
bound a ListBox to that collection, so it’ll be looking for change
notification events—but WPF won’t fully process those changes until
our code has finished with the UI thread. Data binding defers its work
until the dispatcher thread has no higher priority work to do.
That may be the reason why it works if you update the property via the dispatcher. Have you try to force an update in the target via GetBindingExpression(Property).UpdateTarget()2 ?

Nowdays you can do like this
In constructor of the Form/Window
btnAddNewCard.Click += async (s, e) => await BtnAddNewCard_ClickAsync(s, e);
private async Task BtnAddNewCard_ClickAsync(object sender, RoutedEventArgs e)
{
// Any code like
await ShowOKMessageAsync(msg);
}

Related

WPF Combobox Item Update

I am rather new to the WPF setup and I am running into an issue where as far as I can see I have set it up correctly to have my combobox bound to a observable collection of object.
The Combobox will update when I add or delete items. If I make a change the items in the drop down will not show any differently but if I select one that was edited it will now show the new information but only when selected.
I have set up the object class to use INotifyPropertyChanged correctly I think but it does not seem to be functioning. Going to attach the code below so that you can easily see exactly what I am trying to describe.
What I am trying to do it allow a user to push a button and have the text inside a combobox update to show the new text.
Imports System.ComponentModel
Public Class Window2
Public _names As New System.Collections.ObjectModel.ObservableCollection(Of TestClass)
Public Sub BaseLoading() Handles MyBase.Loaded
Dim AddNewItem As New TestClass
AddNewItem.groupName = "Item " + (_names.Count + 1).ToString
_names.Add(AddNewItem)
cbo_Names.SetBinding(ItemsControl.ItemsSourceProperty, New Binding With {.Source = _names})
End Sub
Private Sub button_PreviewMouseDown(sender As Object, e As MouseButtonEventArgs)
Dim AddNewItem As New TestClass
AddNewItem.groupName = "Item " + (_names.Count + 1).ToString
_names.Add(AddNewItem)
_names(0).groupName = ("Value Changed")
End Sub
End Class
Public Class TestClasss
Implements INotifyPropertyChanged
Public _groupName As String = ""
Public Property groupName As String
Get
Return _groupName.ToString
End Get
Set(value As String)
_groupName = value
onPropertyChanged(New PropertyChangedEventArgs(_groupName))
End Set
End Property
Public Event PropertyChagned(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Public Sub onPropertyChanged(ByVal e As PropertyChangedEventArgs)
RaiseEvent PropertyChagned(Me, e)
End Sub
End Class
XAML
<Window x:Class="Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button x:Name="button" Content="Button" PreviewMouseDown="button_PreviewMouseDown"/>
<ComboBox x:Name="cbo_Names" Margin="30,5,30,5" IsEditable="False" ItemsSource="{Binding _names, NotifyOnSourceUpdated=True,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="groupName" SelectedItem="{Binding _names, NotifyOnSourceUpdated=True,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>
I would appreciate any help locating what I am missing.
You should pass the name of the data-bound property (instead of the value of the property) to the constructor of the PropertyChangedEventArgs:
onPropertyChanged(New PropertyChangedEventArgs("groupName"))
If you are using at least Visual Studio 2015, you could consider making the following change to your onPropertyChanged routine:
Public Sub onPropertyChanged(<System.Runtime.CompilerServices.CallerMemberName> Optional ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Then, in the setter for groupName you can call onPropertyChanged without specifying the property name, and it will be taken from the name of the caller (that is, it will end up being "groupName").
Effectively, this is doing the same thing as the previous answer, but in a way that is easier for you to code and maintain. (Along with the <CallerMemberName> attribute, this works well with NameOf, both making your code more robust against any changes in names of properties.)

Binding doesn't get called on code behind propertry

So I have a Grid with some checkboxes, etc inside it and wanted to set them all to readonly , I added the IsEnabled part below:
<Grid IsEnabled="{Binding IsFieldReadOny}">
And in the code behind added this:
Private _isFieldReadOnly As Boolean = True
Public Property IsFieldReadOny() As Boolean
Get
Return _isFieldReadOnly
End Get
Set(value As Boolean)
_isFieldReadOnly = value
End Set
End Property
But when I put breakpoint, it does not get hit or do anything.
If I manually hard code a True for the grid, then it works.
I am new to both WPF and VB syntax, so it might be something easy that I am not doing right.
Here is a very simple example of MVVM and binding with one way out of TONS to do things. Binding in and of itself has many many options of traversing a visual tree with 'RelativeSource' and scoping. As well as mode options and other settings. I chose to focus on keeping it simple though. I just want a view that has a textbox, you can change yourself, a button you can hit, a label that will update from the text you changed.
So here is a basic view:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SimpleWPF"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox Text="{Binding Text}" Height="30" />
<Button Content="Example" Command="{Binding DoCommand}" />
<Label Content="{Binding Output}" Height="30" />
</StackPanel>
</Window>
I want to set up a single helper class for a 'DelegateCommand'. You can do this many ways but essentially I am saving repeat methods for later reuse for commands to help with an ICommand interface.
Public Class DelegateCommand(Of T)
Implements ICommand
Private _execute As Action(Of T)
Public Sub New(execute As Action(Of T))
_execute = execute
End Sub
Public Event CanExecuteChanged As EventHandler
Private Event ICommand_CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
Private Function ICommand_CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
Return True
End Function
Private Sub ICommand_Execute(parameter As Object) Implements ICommand.Execute
_execute.Invoke(DirectCast(parameter, T))
End Sub
End Class
Now in my Code behind of the view it should be pretty minimal except this:
Class MainWindow
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.DataContext = New MainViewModel()
End Sub
End Class
And my MainViewModel is pretty simple in this case is pretty simple and I am only implementing INotifyPropertyChanged. I would usually do most of my stuff like this in a base class and inherit that on larger solutions.
Imports System.ComponentModel
Public Class MainViewModel
Implements INotifyPropertyChanged
Private _text As String
Public Property Text As String
Get
Return _text
End Get
Set(ByVal value As String)
_text = value
OnPropertyChanged(NameOf(Text))
End Set
End Property
Private _output As String
Public Property Output As String
Get
Return _output
End Get
Set(ByVal value As String)
_output = value
OnPropertyChanged(NameOf(Output))
End Set
End Property
Public Sub New()
_text = "Test"
End Sub
Public ReadOnly Property DoCommand As New DelegateCommand(Of Object)(AddressOf DoIt)
Private Sub DoIt(obj As Object)
Output = $"{Text} {DateTime.Now.ToLongDateString}"
End Sub
#Region "Implement INotifyProperty Changed"
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
#End Region
End Class
When you use a generic binding you are looking at the DataContext of the object and by generic I mean a {Binding PropertyName} without any other parameters. In order to bind to a property within your code behind (which I don't recommend doing) then you need to tell the binding to look at that location. You also need to use a dependency property for binding on UIElements since it's already built in.
So to make this work I've named the Window the Grid is in 'window'. Then I've given the binding expression a direct connection to the property.
<Grid IsEnabled="{Binding IsReadOnlyField, ElementName=window}" />
I've then added a binding to the Checkbox as well to the same thing.
<CheckBox Content="Is Grid Enabled" IsChecked="{Binding IsReadOnlyField, ElementName=window}" />
Then in the code behind I've changed the property to a DependencyProperty.
public bool IsReadOnlyField
{
get { return (bool)GetValue(IsReadOnlyFieldProperty); }
set { SetValue(IsReadOnlyFieldProperty, value); }
}
public static readonly DependencyProperty IsReadOnlyFieldProperty =
DependencyProperty.Register(nameof(IsReadOnlyField), typeof(bool), typeof(MainWindow));
This will get the binding working.
If you are not using the code behind and are binding to a ViewModel or any class you should preferably make that class interface INotifyPropertyChanged (although you can also make that ViewModel inherit from DependencyObject and use the same DependencyPropery... It's just normally used for UI elements). Then write the property as normal and in the setter call the property changed event. However, you will most likely set the binding back to the way you had it and just put that ViewModel as the DataContext.
There's A LOT to explain about binding as it can be very flexible and used many different ways. Once you get it though you got it and learning more ways to bind will be simple. I suggest learning exactly how the binding takes place so that you can manipulate and choose the best binding for any situation.

Events not being handled from a user control and main form

I am attempting to handle an event in the application main form where said event is being raised from a user control populated on the main form. I've defined an Interface for the event which is being implemented in both the Main Form and the User Control. I'm using MvvmLight from GalaSoft for the MVVM support.
The main form code behind indicates that the event is attached, but when I do the check in the user control, it indicates that there is no handler attached to the event, so obviously, it won't ever get to the handler.
Any help would be appreciated.
The interface I've defined is pretty basic:
Public Interface IEventFiring
Event EventFiring(sender As Object)
End Interface
My Main Form Xaml looks like this:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:EventFiringFromContolToMainForm"
xmlns:efc="clr-namespace:EventFiringControl;assembly=EventFiringControl"
Title="MainWindow">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding StatusText, Mode=OneWay}"
Height="25"
Margin="5"/>
<Separator Margin="5"/>
<efc:UserControl1/>
</StackPanel>
</Window>
The Code Behind is:
Imports EventFiringControl
Class MainWindow
Implements IEventFiring
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
AddHandler EventFiring, AddressOf EventFiringSub
If EventFiringEvent Is Nothing Then
CType(DataContext, MainWindowViewModel).StatusText = "Event did NOT Attach!!"
Else
CType(DataContext, MainWindowViewModel).StatusText = "Event Attached"
End If
End Sub
Public Event EventFiring(sender As Object) Implements IEventFiring.EventFiring
Private Sub EventFiringSub()
CType(DataContext, MainWindowViewModel).StatusText = "Event Fired"
End Sub
End Class
The view model for the Main Form is:
Imports GalaSoft.MvvmLight
Public Class MainWindowViewModel
Inherits ViewModelBase
Private _statusText As String
Public Property StatusText As String
Get
Return _statusText
End Get
Set(value As String)
_statusText = value
RaisePropertyChanged(Function() StatusText)
End Set
End Property
End Class
Now for the User Control.
Xaml file is:
<UserControl x:Class="UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:EventFiringControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<local:EventFiringViewModel/>
</UserControl.DataContext>
<Grid>
<Button Content="Cancel" Command="{Binding CancelCommand}" Height="50"/>
</Grid>
</UserControl>
The code behind is:
Public Class UserControl1
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
End Class
Finally, the View Model for the User Control is:
Imports GalaSoft.MvvmLight.Command
Imports GalaSoft.MvvmLight
Public Class EventFiringViewModel
Inherits ViewModelBase
Implements IEventFiring
Public ReadOnly Property CancelCommand As RelayCommand
Get
Return New RelayCommand(Sub() CancelSub())
End Get
End Property
Private Sub CancelSub()
If EventFiringEvent IsNot Nothing Then
RaiseEvent EventFiring(Me)
End If
End Sub
Public Event EventFiring(sender As Object) Implements IEventFiring.EventFiring
End Class

wpf lable text binding not working, where i am going wrong

I am new to WPF and trying something like this to update a label text in the WPF form from the class.
The onchange event is getting triggered, but not getting displayed on the form
Here is my class
Public Class ExtractDetails
Inherits UserControl
Implements INotifyPropertyChanged
Private _prdFrstName as string
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Property PrdFrstName() As String
Get
Return _prdFrstName
End Get
Set(ByVal value As String)
If _prdFrstName <> value Then
_prdFrstName = value
Me.OnPropertyChanged("PrdFrstName")
End If
End Set
End Property
Public Sub suMainStrt()
PrdFrstName = strComurl ''contyains teh URL to nagigate to
webBrwFrst = New WebBrowser
webBrwFrst.Navigate(New Uri(strComurl))
Call extract(webBrwFrst, strComurl)
end sub
end class
the url keeps on changing as i ma getting the values from an excel file and looping for each URL.
i wanted to display the URL currently working now
this is my XAML
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Avenet Prduct Description Extractor" Height="396.627" Width="588.123" Background="AliceBlue" Icon="LGIcon.ico">
<Grid Height="341.077" Width="567.721" Background="AliceBlue">
<StackPanel Margin="170.225,226.418,3.143,0" Name="StackPanel1" Height="97.994" VerticalAlignment="Top">
<Label Height="30.906" Name="lblCrntSt1" Content="{Binding Path=PrdFrstName, UpdateSourceTrigger=PropertyChanged}" Width="161" BorderThickness="2" BorderBrush="AliceBlue" Background="Red" Foreground="White" FontSize="13"></Label>
</StackPanel>
</Grid>
and this is my windows class.
Class Window1
Dim clsIniti As New ExtractDetails
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
'clsIniti = New ExtractDetails
Me.DataContext = clsIniti
End Sub
end class
without updating the text labels the entire function is working good. but i wish to display few things. where i am going wrong
I tried data binding by removing few parts to new created project. it works there. so some thing wrong in this code??? :`(
I see two possible causes that this doesn't work for you.
A. How does your OnPropertyChanged method look like?
' Correct implementation:
Private Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
B. Make sure the ExtractDetails instance you call suMainStrt on, is the same as your DataContext instance. Test this by calling suMainStrt directly from the constructor of Window1:
Class Window1
Dim clsIniti As New ExtractDetails
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
'clsIniti = New ExtractDetails
Me.DataContext = clsIniti
' test (if this works, your problem is B.)
clsIniti.suMainStrt()
End Sub
End Class
As a side note: Unless you have good reasons to do this, I suggest you create a dedicated viewmodel (class, not usercontrol) that contains the properties you want to bind to.

WPF ComboBox binding not working as expected

I want my WPF ComboBox's ItemsSource property to be bound to MyListObject's MyList property. The problem is that when I update the MyList property in code, the WPF ComboBox is not reflecting the update. I am raising the PropertyChanged event after I perform the update, and I thought WPF was supposed to automatically respond by updating the UI. Am I missing something?
Here's the CLR object:
Imports System.ComponentModel
Public Class MyListObject
Implements INotifyPropertyChanged
Private _mylist As New List(Of String)
Public Sub New()
_mylist.Add("Joe")
_mylist.Add("Steve")
End Sub
Public Property MyList() As List(Of String)
Get
Return _mylist
End Get
Set(ByVal value As List(Of String))
_mylist = value
End Set
End Property
Public Sub AddName(ByVal name As String)
_mylist.Add(name)
NotifyPropertyChanged("MyList")
End Sub
Private Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
Public Event PropertyChanged(ByVal sender As Object, _
ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
Here is the XAML:
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
xmlns:local="clr-namespace:WpfApplication1"
>
<Window.Resources>
<ObjectDataProvider x:Key="MyListObject" ObjectType="{x:Type local:MyListObject}"/>
</Window.Resources>
<Grid>
<ComboBox Height="23"
Margin="24,91,53,0"
Name="ComboBox1"
VerticalAlignment="Top"
ItemsSource="{Binding Path=MyList, Source={StaticResource MyListObject}}"
/>
<TextBox Height="23"
Margin="24,43,134,0"
Name="TextBox1"
VerticalAlignment="Top" />
<Button Height="23"
HorizontalAlignment="Right"
Margin="0,43,53,0"
Name="btn_AddName"
VerticalAlignment="Top"
Width="75">Add</Button>
</Grid>
</Window>
And here's the simple code-behind:
Class Window1
Private obj As New MyListObject
Private Sub btn_AddName_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) _
Handles btn_AddName.Click
obj.AddName(TextBox1.Text)
End Sub
End Class
Thanks!
You are binding to a list of strings. That list class does not implement Inotifyproperty. You should use an observablecollection instead.
I also notice in your code behind you declare
Private obj As New MyListObject
This is not the static resource you bound the combo box to. So your add call would not be reflected in your view.
The ObservableCollection is most likely the solution, but if it still gives you grief, you can directly access your static resource by calling the following code after your list gets updated:
DirectCast(Me.FindResource("MyListObject"), ObjectDataProvider).Source = _myList
Try using a BindingList(Of T) instead of a List(Of T).
Edit: I am new to WPF and it does look like BindingList isn't a complete solution to your problem, but it might be a step in the right direction. I was able to test the MyListObject converted to BindingList in WinForm and the ListChanged event was raised to the ComboBox which then updated its list.
I found this (possible) solution to wrap your class in an ObservableCollection that might help you solve your problem
Enabling WPF Magic Using WCF - Part 1
This is the code to update your object to a BindingList. Combine your code with the code from that resource and you should be good to go.
Public Class MyListObject
...
'Private _mylist As New List(Of String)
Private _mylist As New BindingList(Of String)
...
'Public Property MyList() As List(Of String)
' Get
' Return _mylist
' End Get
' Set(ByVal value As List(Of String))
' _mylist = value
' End Set
'End Property
Public Property MyList() As BindingList(Of String)
Get
Return _mylist
End Get
Set(ByVal value As BindingList(Of String))
_mylist = value
End Set
End Property
...
End Class

Resources