Wpf Binding Not Updating the View

WPF binding not updating the view

You need to implement INotifyPropertyChanged in your ViewModel order to notify the View that the property has changed.

Here's a link to the MSDN page for it: System.ComponentModel.INotifyPropertyChanged

The most important thing to note is that you should raise the PropertyChanged event in your property setter.

WPF Binding not updating XAML but PropertyChanged called

The reason why the binding to DisplayPopup does not update is that the property is a computed property. A computed property lacks a setter and therefore never raises INotifyPropertyChanged.PropertyChanged. The data binding listens to this event. As the result DisplayPopup.Get is only called once (the moment the binding is initialized).

To solve this you can either let the MainViewModel listen to PropertyChanged events of the ContactViewModel items or as it seems that you are interested in selected items simply bind the ListBox.SelectedItem and change MainViewModel.DisplayPopup on changes.

For simplicity I recommend the second solution.

Note that in order to make the ListBox.IsSelected binding work you must set the ListBox.ItemContainerStyle and target ListBoxItem instead of ListBox:

MainViewModel.cs

public class MainViewModel : BaseViewModel
{
public ObservableCollection<ContactViewModel> TankItems { get; set; }

private ContactViewModel selectedTankItem;
public ContactViewModel SelectedTankItem
{
get => this.selectedTankItem;
set
{
this.selectedTankItem = value;
OnPropertyChanged(nameof(this.SelectedTankItem));

this.DisplayPopup = this.SelectedTankItem != null;
}

// Raises INotifyPropertyChanged.PropertyChanged
public bool DisplayPopup { get; set; }

public MainViewModel() : base()
{
TankItems = new ObservableCollection<ContactViewModel>()
{
new ContactViewModel(),
new ContactViewModel()
};
}
}

MainWindow.xaml

<ListBox ItemsSource="{Binding TankItems}" 
SelectedItem="{Binding SelectedTankItem}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type ContactViewModel}">
<StackPanel>
<TextBlock Text="Test" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

<Border>
<TextBlock Text="{Binding DisplayPopup}" />
</Border>

wpf UI not updating?

You are setting a new value of property here:

AppliedJobsCollection = new ObservableCollection<AppliedJob>(appliedJobsList);

but it's a simple auto-property without notification.

Make it full property (view model needs to implement INotifyPropertyChange):

ObservableCollection<AppliedJob> _appliedJobsCollection =
new ObservableCollection<AppliedJob>(); // empty initially
public ObservableCollection<AppliedJob> AppliedJobsCollection
{
get => _appliedJobsCollection;
set
{
_appliedJobsCollection = value;
RaisePropertyChanged(nameof(AppliedJobsCollection));
}
}

How does the full property behave? Is it as if all entries in each item in the collection have been changed (and thus have their properties changed)?

See this pseudo-code.

// given that AppliedJobsCollection is already initialized

// modify existing collection -> works
// bindings was subscribed to CollectionChanged event and will update
AppliedJobsCollection.Add(new AppliedJob(...));

// change item property -> works
// you implement INotifyPropertyChanged for items
// bindings was subscribed to that and will update
AppliedJobsCollection[0].Company = "bla";

// new instance of collection -> ... doesn't works
// how bindings can update?
AppliedJobsCollection = new ObservableCollection<AppliedJob>(...);

For last scenario to work you need to implement INotifyPropertyChanged for a class containing AppliedJobsCollection property and rise notification.

WPF DataBinding not updating?

In order to support data binding, your data object must implement INotifyPropertyChanged

Also, it's always a good idea to Separate Data from Presentation

public class ViewModel: INotifyPropertyChanged
{
private bool _test;
public bool Test
{ get { return _test; }
set
{
_test = value;
NotifyPropertyChanged("Test");
}
}

public PropertyChangedEventHandler PropertyChanged;

public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

<Window x:Class="TheTestingProject_WPF_.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>
<Viewbox>
<CheckBox IsChecked="{Binding Path=Test, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Viewbox>
</Grid>

Code Behind:

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel{Test = true};
}
}

WPF TreeView Binding not updating the View

The OnPropertyChanged("TestCases"); must be issued by the object that includes the property that changed. In your case, your class TestCaseNode will need to call the OnPropertyChanged method in order for the Treeview to recognize the change to the collection because that object holds the collection. That is, it is not simply some any property named "TestCases" that has changed but the property in a specific object. The reason: you could have more than one properties with this name in different classes. And, if there are multiple copies of the object, they each have a property with the same name.

What I have done, and this has worked for me, is add a public method within the TestCaseNode called UpdateProperties() that then calls OnPropertyChanged("TestCases"); This ensures that the property update is issued by the correct object. Then I call this method when I need to have the control updated.

There are several other ways to do the same thing but I find this a simple and direct approach. You could, for example, include `OnPropertyChanged("TestCases"); in your add method. I have not done this because 1) the OnPropertyChanged call occurs too often and 2) without the OnPropertyChanged call I can defer the update to the control until after I've made several or all of my Add's.

WPF Binding is correct, but window does not update

Your properties need to raise the PropertyChanged event when they are changed. Your class should implement INotifyPropertyChanged

/// <inheritdoc cref="INotifyPropertyChanged"/>
public partial class YourViewModel : INotifyPropertyChanged
{
/// <inheritdoc/>
public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Notifies that a properties value has changed.
/// </summary>
/// <param name="propertyName">The property that has changed.</param>
public virtual void NotifyPropertyChanged([CallerMemberName]string propertyName = null)
{
this.CheckForPropertyErrors();

this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

and then your properties should look like this:

    private QuestionViewModel currentQuestion;
public QuestionViewModel CurrentQuestion
{
get
{
return this.currentQuestion;
}

set
{
this.currentQuestion = value;
this.NotifyPropertyChanged();
}
}


Related Topics



Leave a reply



Submit