Search code examples
c#wpfdynamicpopupdatatrigger

How to Write a Data Trigger to open Popup by Clicking dynamic Button in WPF?


I'm having a dynamic Button in my WPF application, while clicking any one of the button the popup should open and the corresponding Button should turn the Background Color to Orange and rest of the Button should be in default Backgroud Color using DataTrigger and one more condition, at the time of Popup close, the corresponding Button Background Color should turn to the Default Color.

Note: I Can't able to give Name for the Buttons because of Dynamic Creation. Here I placed 5 Buttons without Name Property, Consider the Button as Dynamic Creation

My XAML Source Code is

<Grid>
    <Grid Height="30px" VerticalAlignment="Top" Margin="0,50,0,0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100px"/>
            <ColumnDefinition Width="100px"/>
            <ColumnDefinition Width="100px"/>
            <ColumnDefinition Width="100px"/>
            <ColumnDefinition Width="100px"/>
        </Grid.ColumnDefinitions>
        <Button Content="One" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75"/>
        <Button Content="Two" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75"/>
        <Button Content="Three" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75"/>
        <Button Content="Four" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75"/>
        <Button Content="Five" Grid.Column="4" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75"/>
    </Grid>
    <Grid>
        <Popup Name="sPop" Placement="Mouse" StaysOpen="False">
            <Grid>
                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" Text="Welcome to Popup Screen"/>
            </Grid>
        </Popup>
    </Grid>
</Grid>

Solution

  • You cannot do it using DataTriggers. DataTriggers are for Data-Based scenarios, so if you are using DataBinding, then use them.

    Recommended approach :

    Assign a name to your Popup. And use Behaviors.

    <Button ...>
        <Button.Style>
            <Style TargetType="Button">
                <Style.Triggers>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter Property="Background" Value="Red"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <i:Interaction.Behaviors>
                    <ei:ConditionBehavior>
                        <ei:ConditionalExpression>
                            <ei:ComparisonCondition LeftOperand="{Binding IsFocused, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" RightOperand="True"/>
                        </ei:ConditionalExpression>
                    </ei:ConditionBehavior>
                </i:Interaction.Behaviors>
                <ei:ChangePropertyAction TargetObject="{Binding ElementName=Popup1}" PropertyName="IsOpen" Value="True"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>
    

    To use Blend assemblies :

    Add reference to System.Windows.Interactivity and Microsoft.Expression.Interactions and following namespaces :

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

    To revert back old Background of the source Button :

    <Button>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <i:Interaction.Behaviors>
                    <ei:ConditionBehavior>
                        <ei:ConditionalExpression>
                            <ei:ComparisonCondition LeftOperand="{Binding IsFocused, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" RightOperand="True"/>
                        </ei:ConditionalExpression>
                    </ei:ConditionBehavior>
                </i:Interaction.Behaviors>
    
                <!-- Store Button's old Background -->
                <ei:ChangePropertyAction TargetObject="{Binding ElementName=Popup1}" PropertyName="Tag" Value="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}"/>
    
                <!-- Change Button's Background -->
                <ei:ChangePropertyAction PropertyName="Background" Value="Purple"/>
    
                <!-- Open Popup -->
                <ei:ChangePropertyAction TargetObject="{Binding ElementName=Popup1}" PropertyName="IsOpen" Value="True"/>
    
                <!-- Save this Button, Popup will use it to revert back its old Background -->
                <ei:ChangePropertyAction TargetObject="{Binding ElementName=Popup1}" PropertyName="PlacementTarget" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}"/>
    
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>
    
    <Popup x:Name="Popup1" Placement="Mouse" StaysOpen="False">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Closed">
                <ei:ChangePropertyAction 
                            TargetObject="{Binding PlacementTarget, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Popup}}" 
                            PropertyName="Background" 
                            Value="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Popup}}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <Grid>
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" Text="Welcome to Popup Screen"/>
        </Grid>
    </Popup>