如何通过点击WPF中的动态按钮编写数据触发器来打开弹出菜单

本文关键字:触发器 数据 菜单 何通过 WPF 按钮 动态 | 更新日期: 2023-09-27 18:27:07

我的WPF应用程序中有一个动态按钮,当点击任何一个按钮时,弹出窗口都会打开,相应的按钮应该将背景色变成橙色,按钮的其余部分应该是默认的背景色,使用DataTrigger和另一个条件,在弹出窗口关闭时,则相应的按钮背景颜色应变为默认颜色。

注意:由于动态原因,我无法给出按钮的名称创造在这里我放置了5个没有Name属性的按钮,考虑按钮作为动态创建

我的XAML源代码是

<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>

如何通过点击WPF中的动态按钮编写数据触发器来打开弹出菜单

您不能使用DataTriggers执行此操作。DataTriggers适用于基于数据的场景,因此如果您正在使用DataBinding,请使用它们。

推荐方法:

为弹出菜单指定一个名称。并使用行为。

<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>

使用混合组件:

添加对System.Windows.InteractivityMicrosoft.Expression.Interactions以及以下命名空间的引用:

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

恢复源按钮的旧背景:

<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>    

我试图在不使用DataTrigger的情况下实现您的要求。这是改变背景的简单触发方式:

<Style TargetType="Button">
    <Style.Triggers>
        <Trigger Property="Button.IsFocused" Value="True">
            <Setter Property="Button.Background" Value="Red" />
        </Trigger>
    </Style.Triggers>
</Style>

您的每个按钮都可以处理Click事件:

<Button Content="One" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Click="Button_Click" />
...

我们需要以某种方式拿走你的Popup。我刚刚命名它:

<Popup Name="popup" Placement="Mouse" StaysOpen="False">
...

点击事件很简单:

private void Button_Click(object sender, RoutedEventArgs e) {
    var button = sender as Button;
    if (popup.IsOpen) { popup.IsOpen = false; }
    popup.PlacementTarget = button;
    popup.IsOpen = true;
}

所以它可以随心所欲地工作。