question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

After user click the Expander header, IsExpanded not work by trigger.

See original GitHub issue
  • .NET Core Version:
.NET SDK (反映任何 global.json):
 Version:   5.0.201
 Commit:    a09bd5c86c

运行时环境:
 OS Name:     Windows
 OS Version:  10.0.19042
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.201\

Host (useful for support):
  Version: 5.0.4
  Commit:  f27d337295

.NET SDKs installed:
  2.2.207 [C:\Program Files\dotnet\sdk]
  5.0.201 [C:\Program Files\dotnet\sdk]
  • Windows version: Win10 20H2
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: I don’t know.
  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc…)? If yes, please file the issue via the instructions here.
  • Security issues and bugs should be reported privately, learn more via our responsible disclosure guidelines.

Problem description: I want to expand the Expander when the TextBox has validation error. But after I click the Expander header by mouse once, the IsExpanded property never works.

image

Let’s see, its background is changed, so the trigger is no problem.

image

Actual behavior: After user click the Expander header, Expander.IsExpanded no longer expand the content.

Expected behavior: After user click the Expander header, Expander.IsExpanded should expand the content when it is True.

Minimal repro:

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:14 (7 by maintainers)

github_iconTop GitHub Comments

3reactions
SamBentcommented, Apr 24, 2021

@GF-Huang - I can explain why this is happening, but I don’t see how to achieve the effect you want. I think it needs a new feature.

The problem is an unfortunate interaction between your declaration

    <Expander  IsExpanded="{Binding (Validation.HasError), ElementName=TextBox, Mode=OneWay}">

and a declaration for the Expander’s ToggleButton (from the theme style):

      IsChecked="{Binding Path=IsExpanded,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"

When you click the button, the second binding writes a new value into the expander, essentially calling expander.SetValue(IsExpandedProperty, true). The first time this happens, it overwrites the first binding, which goes away never to return. You can see this using the VS Live Property Explorer: look at the expander’s IsExpanded property in the “Local” section and be prepared to refresh or re-select the expander (the explorer in my version of VS is not as “live” as it should be); before clicking it shows a BindingExpression, after clicking it shows a raw boolean value.

This overwriting wouldn’t happen if your binding were two-way, or if the second binding used SetCurrentValue instead of SetValue. But I don’t see how to use a two-way binding to get your effect, and there’s no way to tell the second binding to use SetCurrentValue. And I haven’t found any other tricks to work around this problem (replacing the second binding, using intermediate properties, intercepting the SetValue call, etc.). Maybe someone in the community is up to the challenge?

Feature request: A setting on Binding that tells it to use SetCurrentValue to write values, if possible. Update Expander’s theme style to use the setting. Locate and update all similar uses.

Alternatively: Breaking change to make Binding always use SetCurrentValue. Of course, only if a deep study proves that it’s always the right thing to do.

History: WPF controls used to use SetValue to change their own properties, which caused hundreds of bugs similar to yours because SetValue overwrites one-way bindings and hides values from styles, triggers, and templates. We introduced SetCurrentValue in .NET 4.0 to fix this, but didn’t consider the indirect case of a two-way binding doing the change. And yours is the first complaint I’m aware of in the 12 years since then. So it’s apparently not a common scenario.

1reaction
schruuuthcommented, Mar 22, 2022

Ran into the same problem, but could replace the Expander with a “selfmade” Expander that is made up of a ToggleButton and content area. The binding with the isChecked Property of the ToggleButton does work as expected unlike the Expanders property.

<StackPanel>
        <Button Command="{Binding ResetCommand}">RESET PROPERTY</Button>
        <Button Content="CloseAll"
                      Command="{Binding CloseAllCategoriesCommand}"></Button>
        <Button Content="ShowAll"
                      Command="{Binding ShowAllCategoriesCommand}"></Button>
        <ItemsControl x:Name="_ItemsControl" Margin="0,20,0,0">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <!--<Expander Header="{Binding Name}"
                              IsExpanded="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=DataContext.ShowAll, Mode=OneWay}">
                        <Border Width="500" Height="300" Background="OrangeRed"></Border>
                    </Expander>-->
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <ToggleButton x:Name="ToggleButton"
                                      Content="{Binding Name}" Background="AliceBlue"
                                      IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=DataContext.ShowAll, Mode=OneWay}" Margin="0,5"></ToggleButton>
                        <Border  Grid.Row="1"
                                 Width="500"
                                Height="150"
                                 Visibility="{Binding ElementName=ToggleButton, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                                Background="OrangeRed"></Border>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
Read more comments on GitHub >

github_iconTop Results From Across the Web

wpf - Expander getting stuck after IsExpanded set to true by ...
I'm using a storyboard in an event trigger for the Button.Click which works, but after it is expanded this way the normal button...
Read more >
how to make expander controle header text not click-able ...
Iam new to WPF , I have a requirement , where if I click on header title of Expander control , it is...
Read more >
Expander not working on first click in UI for WPF
I am using the RadExpander in the RowDetails portion of a GridView. If I set the IsExpanded property to true the expander header...
Read more >
WPF Expander trigger on IsExpanded to change the header
Just a quick tip on how you could change the Expander header content when Expander is in expanded state.I have also modified the...
Read more >
The Expander control - The complete WPF tutorial
By default, the Expander is NOT expanded and therefore looks like it does on the first screenshot. The user can expand it by...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found