使用控件样式,如何根据 ToggleButton.IsChecked 绑定或触发对工具提示内容的更改?

Using a control style, how can you bind or trigger a change to ToolTip contents based on ToggleButton.IsChecked?

我定义了一个共享 ToggleButton 样式,当 IsCheckedtrue 时显示一张图像,而当 IsCheckedfalse 时显示另一张图像。将 IsChecked 绑定到 ViewModel 上的布尔值 属性 可以很好地显示所需的图像,因此我知道正在应用我的样式并且 DataTrigger 绑定到 IsChecked 有效。

我想在 IsChecked 更改时更改 ToolTip 文本,但我很难让它正常工作。理想情况下,我希望 ToolTip 在未选中时说“打开”,在选中时说“关闭”。

问题是 ToolTip 没有连接到可视化树中的 ToggleButton,所以我需要另一种方法来找到 ToggleButton.IsChecked。我正在尝试完全以一种风格来做这件事,因为我周围散布着很多这样的按钮,所以不允许对 VM 进行任何更改。

理想情况下,该解决方案允许我使用 ToggleButton.Tag 来存储文本,并应用 ConverterStringFormat(或 ContentStringFormat)。我已经覆盖了 ContentTemplate 并将其替换为准系统 ContentPresenter 以摆脱典型的 ToggleButton 效果,因此可以在必要时进一步更改。 (也许我已经删除了一些重要的东西来让它工作?idk。)

这是我的风格,可以改变图像,但 ToolTip 永远不会改变。

<!--Toggle button where content is a switch image that's "On" when checked and "Off" when anything else-->
<Style TargetType="ToggleButton" x:Key="OnOffToggleButton" x:Shared="False">
    <!-- this worked to format the initial tooltip contents, but no way to bind.
    <Style.Resources> 
        <Style TargetType="ToolTip">
            <Setter Property="ContentStringFormat" Value="Turn on {0}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding ???}" Value="True">
                    <Setter Property="ContentStringFormat" Value="Turn off {0}"/>
                </DataTrigger> 
            </Style.Triggers>
        </Style>
    </Style.Resources> -->
    <Setter Property="Content" Value="{StaticResource ToggleOffImage}"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <ContentPresenter>
                    <ContentPresenter.ToolTip>
                        <TextBlock>
                            <TextBlock.Style>
                                <Style TargetType="TextBlock">
                                    <!-- this works -->
                                    <Setter Property="Text" Value="{Binding Tag, RelativeSource={RelativeSource Self}, StringFormat=Turn on {0}}"/>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding IsChecked}" Value="True">
                                            <!-- trigger has no effect -->
                                            <Setter Property="Text" Value="{Binding Tag, RelativeSource={RelativeSource Self}, StringFormat=Turn off {0}}"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </TextBlock.Style>
                        </TextBlock>
                    </ContentPresenter.ToolTip>
                </ContentPresenter>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource Self}}" Value="True">
            <Setter Property="Content" Value="{StaticResource ToggleOnImage}"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="ToolTip">
                <Setter.Value>
                    <!-- another thing that does not work -->
                    <TextBlock Text="{Binding Tag, RelativeSource={RelativeSource Self}, StringFormat=Turn off {0}}" />
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

按钮本身的定义类似于:

<ToggleButton Style="{StaticResource OnOffToggleButton}" 
              IsChecked="{Binding IsPoweredOn, Mode=OneWay}" 
              Command="{Binding TogglePowerCommand}" 
              Tag="Device Power"/>

StringFormat 不适用于 ToolTip,因为它可以包含 object 类型的任意内容,而不仅仅是纯文本。但是,ToolTip 公开了一个 属性 ContentStringFormat 供您使用。

Gets or sets a composite string that specifies how to format the Content property if it is displayed as a string.

由于 ToolTip 托管在单独的弹出窗口 window 中,它与 ToggleButton 不属于同一可视化树的一部分,但您可以使用 PlacementTargetToolTip.

Gets or sets the UIElement relative to which the ToolTip is positioned when it opens.

<Style TargetType="ToggleButton" x:Key="OnOffToggleButton" x:Shared="False">
   <Setter Property="Content" Value="{StaticResource ToggleOffImage}"/>
   <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
   <Setter Property="ToolTip">
      <Setter.Value>
         <ToolTip Content="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"
                  ContentStringFormat="Turn on {0}">
         </ToolTip>
      </Setter.Value>
   </Setter>
   <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <ContentPresenter/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
   <Style.Triggers>
        <DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource Self}}" Value="True">
            <Setter Property="Content" Value="{StaticResource ToggleOnImage}"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="ToolTip">
               <Setter.Value>
                  <ToolTip Content="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"
                           ContentStringFormat="Turn off {0}">
                  </ToolTip>
               </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

转换器仍然可以像往常一样在 Content 绑定中应用。

<ToolTip Content="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}, Converter={StaticResource YourConverter}}"
         ContentStringFormat="Turn on {0}">