【问题标题】:Customizing the toggle state of a toggle button in wpf在 wpf 中自定义切换按钮的切换状态
【发布时间】:2010-12-04 16:35:30
【问题描述】:

我想自定义 wpf 中切换按钮的切换状态。我想在打开时将图像设置为切换按钮,并在关闭时设置另一个图像。为此,我想到了使用触发器。这就是我最终做的,

<Window ...>
    <Window.Resources>
        <Image x:Key="OnImage" Source="C:\ON.jpg" />
        <Image x:Key="OffImage" Source="C:\OFF.jpg" />
        <Style x:Key="OnOffToggleImageStyle" TargetType="ToggleButton">
            <Style.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter Property="Content" Value="{StaticResource OnImage}" />
                </Trigger>
                <Trigger Property="IsChecked" Value="False">
                    <Setter Property="Content" Value="{StaticResource OffImage}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <ListBox>
        <ListBox.ItemTemplate>
            <DataTemplate>
                ...
                <ToggleButton IsChecked="{Binding Status}" Width="100" Height="35" Style="{StaticResource OnOffToggleImageStyle}" />
                ...
            </DataTemplate>
        </ListBox.ItemTemplate>
</Window>

上面的 sn-p 似乎只适用于列表框中的两个项目。如果不止一项具有绑定值,status 为 true,则它不起作用(它仅适用于这样的一项)。请告诉我我是否朝着正确的方向前进。还请告诉我实现此目的的其他方法。

【问题讨论】:

    标签: c# wpf controls togglebutton


    【解决方案1】:

    这里的问题是因为您正在使用Image 资源。资源中的Image 是控件的具体实例。它一次只能在一个地方。因此,当您的列表中有多个项目时...

    这应该适合你:

    <Style x:Key="OnOffToggleImageStyle" TargetType="ToggleButton">
     <Style.Triggers>
       <Trigger Property="IsChecked" Value="True">
         <Setter Property="Content">
           <Setter.Value>
             <Image Source="C:\ON.jpg" />
           </Setter.Value>
         </Setter>
       </Trigger>
       <Trigger Property="IsChecked" Value="False">
         <Setter Property="Content">
           <Setter.Value>
             <Image Source="C:\OFF.jpg" />
           </Setter.Value>
         </Setter>
       </Trigger>
     </Style.Triggers>
    </Style>
    

    请注意,您可以通过为资源中的每个图像文件使用ImageSource,然后在Image 中引用它来提高性能。这实际上意味着每个图像只从磁盘加载一次,而不是 2*N 次(其中 N 是列表中的项目数。)

    【讨论】:

    • 上面的sn-p是抛出异常。以下是详细信息,无法将“System.Windows.Controls.Image”类型的内容添加到“System.Object”类型的对象。标记文件中的对象“System.Windows.Controls.Image”出错
    【解决方案2】:

    This answer 会帮助你。在那里我拿了一个 ToggleButton 并将它的样式设置为 TreeView 中的 ToggleButton(用于展开折叠节点的 + / - 部分)。您只需更改绘制 - 和 + 符号的路径,即可显示您的图像。

    这里为您量身定制,只需在您的 C:\ 目录下放一张名为“on.jpg”的图片和另一张名为“off.jpg”的图片,只需复制/粘贴到您的窗口即可:

        <Window.Resources>
            <SolidColorBrush x:Key="GlyphBrush" Color="#444" />
            <ControlTemplate x:Key="toggleButtonTemplate" TargetType="ToggleButton">
                <Grid
                    Width="15"
                    Height="13"
                    Background="Transparent">
                    <Image x:Name="ExpandImage"
                          Source="C:\off.jpg"
                          HorizontalAlignment="Left" 
                          VerticalAlignment="Center" 
                          Margin="1,1,1,1" />                     
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked"
                         Value="True">
                        <Setter Property="Source"
                          TargetName="ExpandImage"
                          Value="C:\on.jpg"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
            <Style x:Key="toggleButtonStyle" TargetType="ToggleButton">
                <Setter Property="Template" Value="{StaticResource toggleButtonTemplate}" />
            </Style>
        </Window.Resources>
        <Grid>
            <ToggleButton Style="{StaticResource toggleButtonStyle}" />
        </Grid>
    

    【讨论】:

    • 上述 sn-p 中的 ExpandImage 是什么?没有称为 ExpandImage 的触发器类型。你能检查一下吗?
    • 模板中图片的名称:。这样 ControlTemplate 可以访问它并修改其属性:
    • 对不起,我没有完整阅读。谢谢。它现在工作。为什么它不适合我?为什么只来一次??
    • 我现在不太确定,等我有 10 分钟的时间,我会看看你的代码,让你知道哪里出了问题。
    【解决方案3】:

    这是一个带有 3 个图像和一个弹出窗口的 ToggleButton:

    1. IsChecked = false 时的图像。
    2. IsChecked = true 时的图像。
    3. IsMouseOver = true 时的图像。

    图像以 BitmapImage 的形式存储在资源中,以避免在触发器上更改视觉效果。

    图像文件必须添加到资源中,然后,添加到项目中“Resoruces”文件夹的文件必须标记为BuildAction = Resource

    当 ToggleButton IsEnabled = false 时,它​​还会对 Image 控件应用不透明度;

    代码:

        <ToggleButton
            x:Name="btnToggleImage"
            Margin="5"
            Width="50"            
            Height="50"
            >
            <ToggleButton.Resources>
                <BitmapImage x:Key="imgNormal" UriSource="/YOURPROJECTNAME;component/Resources/YourUncheckedImage.png"/>
                <BitmapImage x:Key="imgHover" UriSource="/YOURPROJECTNAME;component/Resources/YourHoverImage.png"/>
                <BitmapImage x:Key="imgChecked" UriSource="/YOURPROJECTNAME;component/Resources/YourCheckedImage.png"/>
            </ToggleButton.Resources>
    
            <ToggleButton.Style>
                <Style TargetType="ToggleButton">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ToggleButton">
                                <Image
                                    x:Name="PART_Image"
                                    Source="{StaticResource imgNormal}"
                                    />
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked" Value="true">
                                        <Setter TargetName="PART_Image" Property="Source" Value="{StaticResource imgChecked}"/>
                                    </Trigger>
                                    <Trigger Property="IsMouseOver" Value="true">
                                        <Setter TargetName="PART_Image" Property="Source" Value="{StaticResource imgHover}"/>
                                    </Trigger>
                                     <Trigger Property="IsEnabled" Value="false">
                                        <Setter TargetName="PART_Image" Property="Opacity" Value="0.6"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate> 
                        </Setter.Value>
                    </Setter>
                </Style>
            </ToggleButton.Style>
        </ToggleButton>        
    
        <Popup
            x:Name="popup1"
            PlacementTarget="{Binding ElementName=btnToggleImage}"
            PopupAnimation="Slide"
            IsOpen="{Binding ElementName=btnToggleImage, Path=IsChecked, Mode=TwoWay}"
            StaysOpen="False"
            MinWidth="{Binding ElementName=btnToggleImage, Path=Width}">
            <Grid Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
                <!--<ItemsPresenter/>-->
                <Label Content="Hello Wolrd!"/>
            </Grid>
        </Popup>
    

    【讨论】:

      【解决方案4】:

      就像 Drew Noakes 所说,在我的片段中只有两张图片。所以只有两个项目正常工作。我用下面的 sn-p 解决了这个问题。

      <ToggleButton
          Grid.Row="0"  Grid.Column="2"  Grid.RowSpan="2"
          VerticalAlignment="Center" HorizontalAlignment="Center"
          IsChecked="{Binding Status}"
          Width="100" Height="35">
        <ToggleButton.Resources>
          <Image x:Key="OnImage" Source="C:\ON.jpg" />
          <Image x:Key="OffImage" Source="C:\OFF.jpg" />
        </ToggleButton.Resources>
        <ToggleButton.Style>
          <Style TargetType="ToggleButton">
            <Style.Triggers>
              <Trigger Property="IsChecked" Value="True">
                <Setter Property="Content" Value="{StaticResource OnImage}">
                </Setter>
              </Trigger>
              <Trigger Property="IsChecked" Value="False">
                <Setter Property="Content" Value="{StaticResource OffImage}">
                </Setter>
              </Trigger>
            </Style.Triggers>
          </Style>
        </ToggleButton.Style>
      </ToggleButton>
      

      很简单,我将触发器移到了数据模板中。不知道这是否是你的正确答案。似乎工作正常

      【讨论】:

      • 有趣,我收到错误“System.Windows.Controls.Image”不是“Setter.Value”的有效值;不支持从 Visual 或 ContentElement 派生的值。
      • 感谢您发布此答案。
      猜你喜欢
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      • 2014-06-03
      • 2011-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多