Reputation: 5570
This question deals with a dinky little Winforms GUI. Let it be known that I have basic knowledge of data bindings and INotifyPropertyChanged and use both in my ViewModels in WPF. But I don't know Winforms. This is for a school assignment.
So I have a class that has a DisplayName
property. I also have a ListBox
whose Items
are a sequence of instances of my class. I have pointed myListBox.DisplayMember = "DisplayName";
After changing a value in an instance of my class that will cause the DisplayName
property to return a different value, how do I tell my ListBox
to pull the DisplayName
property again to refresh its value?
Upvotes: 4
Views: 3745
Reputation: 183
Here is solution code that does everything in XAML as opposed to back end C#. This is how I do my projects utilizing MVVM (minimizing the back end code, and if possible having no back end code)
<ListBox x:Name="lstServers" HorizontalAlignment="Left" Height="285" Margin="20,37,0,0" VerticalAlignment="Top" Width="215"
ItemsSource="{Binding Settings.Servers}"
SelectedItem="{Binding Settings.ManageSelectedServer, Mode=TwoWay}"
DisplayMemberPath="UserFriendlyName"/>
This is a listbox on the Window. The keys to point out here, which can be very tricky, are the usual ItemsSource property being set to a Settings object on my view model, which has a Servers Observable collection.
Servers is a class that has a property called UserFriendlyName.
public sealed class AutoSyncServer : ObservableModel
{
public AutoSyncServer()
{
Port = "80";
UserFriendlyName = "AutoSync Server";
Server = "localhost";
}
private string _userFriendlyName;
public string UserFriendlyName
{
get { return _userFriendlyName;}
set
{
_userFriendlyName = value;
OnPropertyChanged("UserFriendlyName");
}
}
This is a partial code snippet for you of the class itself.
The SelectedItem of the ListBox is bound to an instance of the Selected object that I store in the model view called ManageSelectedServer.
The tricky part here is the DisplayMemberPath is set to "UserFriendlyName" as opposed to "{Binding UserFriendlyName}". This is key
If you use {Binding UserFriendlyName} it will display the UserFriendlyNames in the collection but will not reflect any changes to that property.
The XAML for the TextBox where the user can update the user friendly name (which should change the text in the listbox also) is:
<TextBox x:Name="txtDisplayName" HorizontalAlignment="Left" Height="23" Margin="395,40,0,0" TextWrapping="Wrap"
Text="{Binding ElementName=lstServers,Path=SelectedItem.UserFriendlyName, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Top" Width="240"/>
This sets the Text property of the TextBox and binds it to the ListBox element lstServers SelectedItem property UserFriendlyName. I've also included an UpdateSourceTrigger=PropertyChanged so that any changes made to the text source notify that they have been changed.
XAML is tricky!
Upvotes: -1
Reputation: 60
I know this was ages ago but I had similar problem and could not find satisfying solution and finally solved with this single line at the end after updating the values:
bindingsource.EndEdit();
Items on listbox reflects any changes entered into textboxes after Update button clicked. So after lines like this:
textbox1.DataBindings["Text"].WriteValue();
textbox2.DataBindings["Text"].WriteValue();
just insert this line:
bindingsourcevariable.EndEdit();
Hope this helps others who also encounter similar problem but haven't found the right solution
Upvotes: 0
Reputation: 824
I needed to do the same thing but with a combobox. The workaround I found is to clear and reset the DisplayMember property.
This worked:
myComboBox.DisplayMember = null;
myComboBox.DisplayMember = "DisplayName";
It's important to note that this is perhaps not the best solution as it will cause multiple SelectedValueChanged events but the end result is successful.
Upvotes: 5
Reputation: 273429
Doing it this way probably requires re-binding the listbox, loosing selectedIndex etc.
One workaround is to forget about the DisplayMember property and handle the Format event of the ListBox instead. Something like (from memory) :
// untested
e.Value = (e.Item as MyClass).DisplayValue;
Upvotes: 2