C# 在 wpf 中自定义切换按钮的切换状态
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1532573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Customizing the toggle state of a toggle button in wpf
提问by sudarsanyes
I wanna customize the toggle state of the toggle button in wpf. I want to set a image to the toggle button when it is on and set another image when it is off. TO do so, i thought of using triggers. This is how i ended up doing,
我想自定义 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>
The above snippet seems to works fine only for two items in the list box. If more than one item has the binding value, status to be true, it doesn't work (it works for only one such item). Please tell me whether I am proceeding in the correct direction. Also tell me other ways of achieving this.
上面的代码片段似乎只适用于列表框中的两个项目。如果多个项目具有绑定值,状态为真,则它不起作用(它仅适用于一个这样的项目)。请告诉我我是否朝着正确的方向前进。还告诉我实现这一目标的其他方法。
采纳答案by Drew Noakes
The issue here is because you are using Image
resources. The Image
in your resources is a concrete instance of a control. It can only be in one place at a time. So when you have more than one item in your list...
这里的问题是因为您正在使用Image
资源。在Image
你的资源是一个控制的具体实例。它一次只能在一个地方。因此,当您的清单中不止一项时...
This should work for you:
这应该适合你:
<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>
Note that you can improve the performance of this by using an ImageSource
for each image file in your resources, then referencing this in the Image
. This effectively means that each image is only loaded once from disk, rather than 2*N times (where N is the number of items in your list.)
请注意,您可以通过ImageSource
对资源中的每个图像文件使用,然后在Image
. 这实际上意味着每个图像仅从磁盘加载一次,而不是 2*N 次(其中 N 是列表中的项目数。)
回答by Carlo
This answerwill help you. In there I took a ToggleButton and styled it to look as the ToggleButton in a TreeView (the + / - part to expand collapse nodes). You'll just need to change the paths that draw the - and + signs, to show your images instead.
这个答案会帮助你。在那里,我使用了一个 ToggleButton 并将它的样式设置为 TreeView 中的 ToggleButton(用于展开折叠节点的 + / - 部分)。您只需要更改绘制 - 和 + 符号的路径,即可显示您的图像。
Here goes personalized to you, just put an image called "on.jpg" and another one called "off.jpg" under your C:\ directory, and it should work by just copy/pasting into your window:
这是针对您的个性化设置,只需在您的 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>
回答by sudarsanyes
Like Drew Noakes said, in my snippte there were only two images. So only two items were working properly. I solved this issue with the following snippet.
就像 Drew Noakes 所说的,在我的片段中只有两张图片。所以只有两个项目正常工作。我用以下代码段解决了这个问题。
<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>
Simple, I moved the triggers in to the data template. Dunno whether this is the correct answer thou'. Seems to be working
很简单,我将触发器移到了数据模板中。不知道这是否是你的正确答案。似乎正在工作
回答by JoanComasFdz
Here is a ToggleButton with 3 images and a popup:
这是一个带有 3 个图像和一个弹出窗口的 ToggleButton:
- An image for when IsChecked = false.
- An image for when IsChecked = true.
- An image for when IsMouseOver = true.
- IsChecked = false 时的图像。
- IsChecked = true 时的图像。
- IsMouseOver = true 时的图像。
The images are stored in resources as BitmapImage in order to avoid changing Visuals on trigers.
图像作为 BitmapImage 存储在资源中,以避免更改触发器上的视觉效果。
The image files have to be added to resources and then, the files added to the "Resoruces" folder in the project have to be marked as BuildAction = Resource.
图像文件必须添加到资源中,然后添加到项目中“资源”文件夹的文件必须标记为BuildAction = Resource。
It also applies an opacity to the Image control when the ToggleButton IsEnabled = false;
当 ToggleButton IsEnabled = false 时,它还对 Image 控件应用不透明度;
Code:
代码:
<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>