wpfbindingsettingsischecked

WPF: Binding RadioButton 'IsChecked' to Settings.Default always setting to 'false'


I have been reading up on how to bind the 'IsChecked' property of a RadioButton to a boolean setting in Settings.Default (all in XAML). Now what I want to achieve is that everytime a radiobutton is chcked, the corresponding setting gets updated and saved. My code looks like this:

Global resource to access the application settings in App.xaml:

xmlns:properties="clr-namespace:MyApp.Properties"

<Application.Resources>
     <ResourceDictionary>
          <properties:Settings x:Key="Settings" />
     </ResourceDictionary>
</Application.Resources>

Then I have a settings page with 2 RadioButtons for the boolean setting 'IsShortProgramFlow' ("On" and "Off").

The radiobuttons are declared like this:

<RadioButton Name="rbShortProgramFlowNo" Content="Off" GroupName="programFlow"> </RadioButton>
<RadioButton Name="rbShortProgramFlowYes" IsChecked="{Binding Source={StaticResource Settings}, Path=Default.IsShortProgramFlow, Mode=TwoWay}" Content="On" GroupName="programFlow"></RadioButton>

As you can see, the first radiobutton doesn't have a binding as it makes things even worse. Also, I am sure that the binding path is correct and thus the settings are accessed correctly.

In my code-behind, I registered the 'Settings.Default.PropertyChanged' to implement auto-save functionality. Constructor of the page:

 Settings.Default.PropertyChanged -= Default_PropertyChanged;
 Settings.Default.PropertyChanged += Default_PropertyChanged;

Method:

 private void Default_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (isInitialisation)
            return;

        Settings.Default.Save();
    }

Now the problem: the setting is always set to 'false' as soon as the page is opened, closed and opened again. So when the setting is set to 'true' and I open the page, the radiobutton is checked as it should be. But when I close the page and open it again (via Frame Navigation), the setting is somehow set to "false" without any user interaction and the radiobutton is not checked.

I am sure that no other code part is accessing the setting, so what could be the cause for this behavior?


Solution

  • I believe that the cause of the described behavior is that the page, after it is closed, never gets garbage collected. So if multiple instances of the page access the Settings.Default via Bindings, something goes wrong. My working solution is to do some manual "garbage collecting" in the Page_Unloaded event:

    private void Page_Unloaded(object sender, RoutedEventArgs e)
        {
            //stop anything that might keep the page alive
            Settings.Default.PropertyChanged -= Default_PropertyChanged;
            someDispatcherTimer.Stop(); 
    
            //clear the checkbox bindings to keep the binding working when the page is loaded again
            UiHelper.FindVisualChildren<RadioButton>(settingsTabControl).ToList().ForEach(rb => BindingOperations.ClearBinding(rb, RadioButton.IsCheckedProperty));
        }
    

    Note that UiHelper.FindVisualChildren() returns a list of all radiobuttons with a binding on my page.