Question

I have bound a ListBox to my ViewModel including the ListBox.SelectedItem. I want to change a visual state depending on if there is one selected or not, but The following doesn't update the state initially, so it stays in the wrong state:

<DataStateBehavior Binding="{Binding SelectedCamera}" Value="{x:Null}" TrueState="CameraSettingsUnselected" FalseState="CameraSettingsSelected"/>

Why is that and how to fix it?

Was it helpful?

Solution

The problem here seems to be that the binding initially evaluates to null and thus doesn't fire the change notification required for the evaluation and state change.

I've fixed it with the following subclass:

public class FixedDataStateBehavior: DataStateBehavior
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += (sender, routedEventArgs) =>
            {
                var bindingExpression = BindingOperations.GetBindingExpression(this, BindingProperty);
                SetCurrentValue(BindingProperty,new object());
                bindingExpression.UpdateTarget();
            };
    }
}

and used it like this:

<FixedDataStateBehavior Binding="{Binding SelectedCamera}" Value="{x:Null}" TrueState="CameraSettingsUnselected" FalseState="CameraSettingsSelected"/>

OTHER TIPS

The answer above works, but I ended up creating a more generic Behavior class that would simply work with all bindings without needing to specify them individually.

public class RefreshDataContextBehavior : Behavior<FrameworkElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        this.AssociatedObject.Loaded += AssociatedObject_Loaded;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        var dc = this.AssociatedObject.DataContext;
        this.AssociatedObject.DataContext = null;
        this.AssociatedObject.DataContext = dc;
    }
}

Then simply insert it into the XAML like so on the object which has the DataContext:

<i:Interaction.Behaviors>
    <local:RefreshDataContextBehavior />
</i:Interaction.Behaviors>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top