I'm quite new at WPF and recently encountered a problem. I got an ObservableCollection< TankCar> TankCars in my ViewModel which is the Binding Source for a ListBox in the view. The ListBox has ItemTemplate that defines two behaviors:
<i:Interaction.Behaviors>
<ei:DataStateBehavior x:Name="Type62DataStateBehavior" Binding="{Binding Type}" Value="62" TrueState="IsType62"/>
<ei:DataStateBehavior x:Name="Type66DataStateBehavior" Binding="{Binding Type}" Value="66" TrueState="IsType66"/>
</i:Interaction.Behaviors>
When I add items to the collection, I can see them appear in the list. But the state is not shown until I call TankCars[i].RaisePropertyChanged("Type")
Moreover, when I need to switch to another collection, I call the code:
TankCars = new ObservableCollection<TankCar> (GetTankCars());
RaisePropertyChanged("TankCars"); //to notify the ListBox
foreach (var car in TankCars) {car.RaisePropertyChanged("Type");} //make states change (not working)
and it appears that after I change ItemSource binding through raising TankCars property change event, items states are not shown (TankCar PropertyChangedEvent is not bound to anything at the moment). If I place a button on a form, that launches the command that calls car.RaisePropertyChanged("Type") for the items, it refreshes the items states.
So the question is: how to make things right to make the behavior of the items trigger after adding new items to a collection and after replacing it by another one? And why the items states are not refreshed, when I raise PropertyChanged just after the changing ListBox item source?
Update: solved with the code below (also helped this answer). And no more manual raising PropertyChanged for collection items, I'm happy :)
public class SmartDataStateBehavior : DataStateBehavior
{
protected override void OnAttached()
{
base.OnAttached();
if (AssociatedObject != null)
{
AssociatedObject.Loaded += AssociatedObjectLoaded;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (AssociatedObject != null)
{
AssociatedObject.Loaded -= AssociatedObjectLoaded;
}
}
private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
{
if (Binding == null || Value == null) return;
if (Binding.ToString() == Value.ToString())
{
if (TrueState != null)
VisualStateManager.GoToElementState(AssociatedObject, TrueState, true);
}
else
{
if (FalseState != null)
VisualStateManager.GoToElementState(AssociatedObject, FalseState, true);
}
}
}