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 != 开发者_StackOverflow中文版null)
VisualStateManager.GoToElementState(AssociatedObject, FalseState, true);
}
}
}
When you have just added the items the respective containers with their behaviours have not yet been created and hence the type is not bound yet, making the notification meaningless.
You normally should not need to raise notifications outside the setter of a property, so i would try to avoid doing all that manually.
I do not know what your behavior does but if it affects the type somehow you should put that notification logic either into the setter of type if it has one or into the OnAttached
override method of the bahaviour.
精彩评论