【问题标题】:Hover over a button and highlight multiple controls when condition is met (MVVM)满足条件时将鼠标悬停在按钮上并突出显示多个控件 (MVVM)
【发布时间】:2016-08-13 22:54:00
【问题描述】:

我有两个绑定了命令的按钮。 如果用户将鼠标悬停在 button1 上,它应该突出显示(边框颜色更改) textbox1 和 combobox1 仅当 button1 处于禁用状态时。

如果用户将鼠标悬停在按钮2上,它应该突出显示(边框颜色更改) textbox2、textbo3 和 combobox1 仅当 button2 处于 禁用状态时。

最后取消突出显示 mouseleave 上的控件。

这对于纯 XAML 是否可行,因为样式应该应用于其他控件,而不是触发事件的按钮本身,并且仅在满足条件时才应用? 怎么可能做到这一点?

我在 SO 上找到了很多示例,但它们不适用于这个特定案例。

我开始以编程方式执行此操作:

<Button Name="btnGenerateHash"  
        IsEnabled="{Binding VM.IsGenerateButtonEnabled}"
        Command="{Binding GenerateCommand}"
        Content="{Binding VM.GenerateHashButtonLabel}" Width="160"                      
        Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Margin="10" >
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <i:InvokeCommandAction Command="{Binding HighlightFieldsCommand}" CommandParameter="{Binding Source='generate,enter'}"></i:InvokeCommandAction>
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseLeave">
            <i:InvokeCommandAction Command="{Binding HighlightFieldsCommand}" CommandParameter="{Binding Source='generate,leave'}"></i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

修改版:

<StackPanel Orientation="Vertical">
<CheckBox 
x:Name="EnableButton1CheckBox" 
Content="Enable Button1" 
Margin="4"
/>

<Grid Margin="4">

<Button   Click="button1_Click"
Content="Button1"
x:Name="button1"
IsEnabled="{Binding IsChecked, ElementName=EnableButton1CheckBox}">

</Button>



<Border
x:Name="Button1MouseDetector"
Background="Transparent"
>
    <Border.Style>
        <Style TargetType="Border">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Tag" Value="MouseOver" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
</Border>


    <!-- 
When button1 is disabled, it can't receive mouse events, so we create a 
coextensive control that's explicitly transparent. If it merely had no  
background specified, it wouldn't get mouse events either. 
-->

</Grid>


<Grid Margin="4">
<Button  
Content="Button2"
x:Name="button2"
IsEnabled="{Binding IsChecked, ElementName=EnableButton1CheckBox}">

</Button>



<Border
x:Name="Button2MouseDetector"
Background="Transparent"
>
    <Border.Style>
        <Style TargetType="Border">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Tag" Value="MouseOver" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
</Border>


    <!-- 
When button1 is disabled, it can't receive mouse events, so we create a 
coextensive control that's explicitly transparent. If it merely had no  
background specified, it wouldn't get mouse events either. 
-->

</Grid>      

<TextBox  
Text="tb1"
x:Name="tb1"
Margin="4"
>
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition 
                Binding="{Binding Tag, ElementName=Button1MouseDetector}" 
                Value="MouseOver" 
                />
                <Condition 
                Binding="{Binding IsEnabled, ElementName=button1}" 
                Value="False" 
                />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush" Value="Red" />
        </MultiDataTrigger>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition 
                Binding="{Binding Tag, ElementName=Button2MouseDetector}" 
                Value="MouseOver" 
                />
                <Condition 
                Binding="{Binding IsEnabled, ElementName=button2}" 
                Value="False" 
                />
            </MultiDataTrigger.Conditions>
            <Setter Property="BorderBrush" Value="Green" />
        </MultiDataTrigger>
    </Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>

【问题讨论】:

  • 可能会给 button1 一个带有触发器的样式,在鼠标悬停时将 Tag 设置为某个东西,然后给其他人样式的 multitriggers 绑定到 button1.Tag 和 button1.IsEnabled。其他人也有类似的交易。
  • 如果你能提供一些很棒的代码。不想输入那么多
  • @EdPlunkett,对你来说 :-) lokusking 很快 :-)。但它应该只在按钮处于禁用状态时触发......?
  • @Legends 如果那是给我的,请参阅编辑,哎呀
  • 是条件属性="IsEnabled" Value="False"

标签: c# wpf xaml


【解决方案1】:

这是部分内容,但说明了如何

  1. 将可能禁用的控件的鼠标悬停状态公开给其他控件上的 XAML 样式触发器,以及

  2. 只有当两个不同的条件都为真时,那些其他 XAML 触发器才能做事。

XAML:

<StackPanel Orientation="Vertical">
    <CheckBox 
        x:Name="EnableButton1CheckBox" 
        Content="Enable Button1" 
        Margin="4"
        />
    <Grid
        Margin="4"
        >
        <Button 
            Content="Button1"
            x:Name="button1"
            IsEnabled="{Binding IsChecked, ElementName=EnableButton1CheckBox}"
            >
        </Button>
        <!-- 
        When button1 is disabled, it can't receive mouse events, so we create a 
        coextensive control that's explicitly transparent. If it merely had no  
        background specified, it wouldn't get mouse events either. 
        -->
        <Border
            x:Name="Button1MouseDetector"
            Background="Transparent"
            >
            <Border.Style>
                <Style TargetType="Border">
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Tag" Value="MouseOver" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Border.Style>
        </Border>
    </Grid>

    <Button 
        Content="Button2"
        x:Name="button2"
        Margin="4"
        >
        <Button.Style>
            <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition 
                                Binding="{Binding Tag, ElementName=Button1MouseDetector}" 
                                Value="MouseOver" 
                                />
                            <Condition 
                                Binding="{Binding IsEnabled, ElementName=button1}" 
                                Value="False" 
                                />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="BorderBrush" Value="Red" />
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>
</StackPanel>

【讨论】:

  • 我正在玩你的示例,我已将 button2 更改为文本框。当我将鼠标悬停在 button1 上时, tb2 的边框变为红色。我在 tb 中输入了一些字符,鼠标悬停效果消失了,当我将鼠标悬停在 button1 上时,它不会再变红了。还有一个问题:Textbox2 可以突出显示,当悬停在禁用的按钮 1 和禁用的按钮 2 上时,就像上面的帖子中提到的那样。如何将 Button2MouseDetector 也绑定到 textbox2? Textbox2 可以通过两个按钮突出显示。
  • @Legends 使用文本框,您可能会看到 FocusVisualStyle 覆盖您正在设置的边框 - 如果您创建第二个文本框(或任何可以接收焦点的内容)并将焦点移至那?或者尝试在文本框上设置 FocusVisualStyle="{x:Null}" 看看是否会改变它。
  • @Legends 对于 textBox2 样式,您将有两个触发器,第一个触发器与我的示例中的 Button1MouseDetector.Tag/button1.IsEnabled 完全相同,另一个与第一个触发器相同,只是它看起来在 Button2MouseDetector.Tag 和 button2.IsEnabled。这就是您在触发器中执行“或”的方式:只需为另一个条件创建第二个触发器。
  • @Legends 哦对了!当它的按钮 IsEnabled 时,您必须通过将可见性设置为折叠来为边框提供隐藏边框的触发器。抱歉,忘记了那部分!
  • 这样解决,完美运行:`
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
相关资源
最近更新 更多