netraju
netraju

Reputation: 141

WPF Expander IsExpanded binding

I have an Expander control with its IsExpanded property bound to a bool in the mvvm model. The binding works fine until you dont touch the expander. Once you click the arrow in the expander to expand, the binding stops working. Setting the bool ShowPreview to false in the model doesn't collapse the expander.

<Expander Name="pExpander" 
          IsExpanded="{Binding Path=ShowPreview,Mode=OneWay}"
          Header="Preview">
    <TextBlock Text="{Binding Path=Message, Mode=OneWay}"></TextBlock>    
</Expander>

Upvotes: 14

Views: 20802

Answers (5)

AntonK
AntonK

Reputation: 1310

In my case (.NET Framework 4) the setter for the expanded wasn't called, because its binding required UpdateSourceTrigger=PropertyChanged, and setting Mode=TwoWay (as proposed in other answer) couldn't solve this issue.
I've ended up with following XAML:

<Expander x:Name="GroupExpander"
          IsExpanded="{Binding IsExpanded, UpdateSourceTrigger=PropertyChanged}"/>

My Expander is in a DataGridTemplateColumn (in a row).

Upvotes: 0

Tonio
Tonio

Reputation: 743

With Silverlight I do this:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

<Expander Name="pExpander" IsExpanded="True" Header="Preview">
    <i:Interaction.Triggers>
        <ei:PropertyChangedTrigger Binding="{Binding ShowPreview, Mode=OneWay}">
            <ei:ChangePropertyAction PropertyName="IsExpanded" Value="{Binding ShowPreview, Mode=OneWay}"/>
        </ei:PropertyChangedTrigger>
    </i:Interaction.Triggers>
    <TextBlock Text="{Binding Path=Message, Mode=OneWay}"></TextBlock>    
</Expander>
<Expander Name="pExpander1" IsExpanded="True" Header="Preview 1">
    <i:Interaction.Triggers>
        <ei:PropertyChangedTrigger Binding="{Binding ShowPreview, Mode=OneWay}">
            <ei:ChangePropertyAction PropertyName="IsExpanded" Value="{Binding ShowPreview, Mode=OneWay}"/>
        </ei:PropertyChangedTrigger>
    </i:Interaction.Triggers>
    <TextBlock Text="{Binding Path=Message1, Mode=OneWay}"></TextBlock>    
</Expander>
//...

The binding is not lost when you manualy expand/collapse one Expander...

Upvotes: 1

Aran Mulholland
Aran Mulholland

Reputation: 23935

Do three things,

Make sure your ViewModel is implementing INotifyPropertyChanged. Your ui wont know about the change if your view model doesnt inform it when the property changes

Change the Mode to TwoWay, you want your view model updated when the expander changes and you want your expander updated when the view model changes

Lastly if the above two don't work use a debug converter to ascertain if your binding is failing. there is an example here of how to do this. This is a technique every wpf developer needs.

I know there was an issue with radio buttons that they would lose their bindings when another button in the group was set, i don't think that is the issue here, however a debug converter will help you figure this out.

Upvotes: 0

imekon
imekon

Reputation: 1523

What caught me out here is that IsExpanded is OneWay by default, so

<Style TargetType="TreeViewItem">
    <Setter Property="IsExpanded" Value="{Binding Expanded}"/>
</Style>

doesn't work the way I expected. Only if you add Mode=TwoWay, then it works (i.e. the item starts paying attention to my Expanded property, and updating it), as in

<Style TargetType="TreeViewItem">
    <Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay}"/>
</Style>

Upvotes: 7

user7116
user7116

Reputation: 64068

If you remove Mode=OneWay does that fix the problem?

Upon reading your other CTQ (changes to the GUI do not affect the model), I don't have a good suggestion for how to limit the change being seen by the underlying data. What is the difference in:

myModel.MyProperty = true; // in *your* code behind

And

myModel.MyProperty = true; // done by a binding

Upvotes: 7

Related Questions