views:

1069

answers:

2

Hi,

I am trying to create a situation where one or none of a grouping of two ToggleButtons can be on at any time. The problem that I have is if I change the state of the backing variable the UI state does not update.

I do have INotifyPropertyChanged implimented.

I've created my ToggleButtons like this:

        <ToggleButton IsChecked="{Binding Path=IsPermanentFailureState, Mode=TwoWay}"
                      HorizontalContentAlignment="Center"
                      VerticalContentAlignment="Center">
            <TextBlock TextWrapping="Wrap" 
                       TextAlignment="Center">Permanent Failure</TextBlock>
        </ToggleButton>
        <ToggleButton IsChecked="{Binding Path=IsTransitoryFailureState, Mode=TwoWay}"
                      HorizontalContentAlignment="Center"
                      VerticalContentAlignment="Center">
            <TextBlock TextWrapping="Wrap" 
                       TextAlignment="Center">Temporary Failure</TextBlock>
        </ToggleButton>

This is my backing properties (I am using the MVVM pattern, the other bindings work, IE clicking on the ToggleButton does enter these property settings. When I'm changing the state via code, the Toggle Buttons don't change visual state. IE I am setting the backing property to false, but the button stays checked.

    public bool? IsPermanentFailureState
    {
        get { return isPermFailure; }
        set
        {
            if (isPermFailure != value.Value)
            {
                NotifyPropertyChanged("IsPermanentFailureState");
            }
            isPermFailure = value.Value;
            if (isPermFailure) IsTransitoryFailureState = false;
        }
    }

    public bool? IsTransitoryFailureState
    {
        get { return isTransitoryFailureState; }
        set
        {
            if (isTransitoryFailureState != value.Value)
            {
                NotifyPropertyChanged("IsTransitoryFailureState");
            }
            isTransitoryFailureState = value.Value;
            if (isTransitoryFailureState) IsPermanentFailureState = false;
        }
    }
+4  A: 

The problem is just that you're raising the property change notification prior to actually changing the property value. Therefore, WPF reads the old value of the property, not the new. Change to this:

public bool? IsPermanentFailureState
{
    get { return isPermFailure; }
    set
    {
        if (isPermFailure != value.Value)
        {
            isPermFailure = value.Value;
            NotifyPropertyChanged("IsPermanentFailureState");
        }
        if (isPermFailure) IsTransitoryFailureState = false;
    }
}

public bool? IsTransitoryFailureState
{
    get { return isTransitoryFailureState; }
    set
    {
        if (isTransitoryFailureState != value.Value)
        {
            isTransitoryFailureState = value.Value;
            NotifyPropertyChanged("IsTransitoryFailureState");
        }
        if (isTransitoryFailureState) IsPermanentFailureState = false;
    }
}

Incidentally, you say it works when you use the interface rather than code, but I can't see it possibly could.

HTH, Kent

Kent Boogaart
You beat me to it Kent. Have an up arrow from me.
Pete OHanlon
wow -- I'm not supposed to be this stupid! That's probably what happens when you sit and code alone all the time. Thanks!
Pieter Breed
A: 

Your code looks wrong: you're notifying change before you've made it. I think you need to move your isPermFailure = value.Value; inside:

        if (isPermFailure != value.Value)            
        {
            isPermFailure = value.Value;
            NotifyPropertyChanged("IsPermanentFailureState");
        }

and likewise for the other one.

I think you'll want to move the other statement in there, too:

        if (isPermFailure != value.Value)            
        {
            isPermFailure = value.Value;
            NotifyPropertyChanged("IsPermanentFailureState");
            if (isPermFailure) 
                IsTransitoryFailureState = false;
        }

otherwise you'll be setting state and notifying on that one, unnecessarily.

serialhobbyist
Regarding your last comment: no it won't notify unnecessarily. All it will do is invoke the property unnecessarily. The setter logic will only result in notification if the underlying field has changed.
Kent Boogaart
You're absolutely right: careless choice of words but I still think mine is the better answer. :-)
serialhobbyist