我整晚都在敲打这个。我想做的就是有一个内容控件,可以根据ViewModel中的布尔值在显示两个不同的按钮之间切换。
基本上我有一个任务在后台运行,带有取消按钮。一旦你点击取消并且任务停止,取消按钮应该变为后退按钮。这是两个单独的按钮元素,而不仅仅是更改单个按钮的属性。我正在使用MahApps TransitioningContentControl,所以我希望能够使用转换。
如果在XAML中大部分都可以完成,我会很高兴。我真的不想为一些简单的东西添加一堆样板代码。
编辑:这是代码片段。没有多少,因为我刚刚删除了所有无效的内容。
<Controls:TransitioningContentControl x:Name="CancelBackButtonControl" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Height="80">
<Canvas>
<Button x:Name="CancelButton" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Style="{DynamicResource MetroCircleButtonStyle}" Height="80" IsCancel="True" Content="{StaticResource appbar_close}" BorderBrush="Black" Command="{Binding CancelCommand}"/>
<Button x:Name="GoBackButton" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Style="{DynamicResource MetroCircleButtonStyle}" Height="80" IsCancel="True" Content="{StaticResource appbar_arrow_left}" BorderBrush="Black" Command="{Binding GoBackCommand}"/>
</Canvas>
</Controls:TransitioningContentControl>
答案 0 :(得分:5)
有很多方法可以实现这一目标(这就是WPF的美妙之处);但是,在我个人看来,如果你只是使用一个来自ToggleButton
的控件,例如RadioButton
,那么你的工作就会更少“,特别是因为你希望它完成所有在XAML中。重要的是不要通过视觉效果来考虑任何控件,而应考虑它们的功能。我之前用RadioButton
完成了一些令人难以置信的事情,所以这是我要展示的第一件事;但是,常规按钮方法包含在本答复的后半部分中。
以下是两种方法(RadioButton
和Button
)的完整示例,完全在XAML中完成:
预览强>
<强>代码:强>
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type RadioButton}" x:Key="FlatRadioButtonStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="Background" Value="#FF346FD6"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="5,2,5,3"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
<ContentPresenter Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FF6696E9"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<RadioButton x:Name="BackButton" Content="Back">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource FlatRadioButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=CancelButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
<RadioButton x:Name="CancelButton" Content="Cancel" IsChecked="True">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource FlatRadioButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=BackButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
</Grid>
</Window>
大多数资源样式代码都是视觉样式和模板,专注于使单选按钮看起来像常规按钮,因此它并不重要。我们将关注的领域是Triggers
。您会注意到,在资源样式中,我确保在检查RadioButton
时它会崩溃。但是,在每个按钮的本地样式中,我确保在检查其他RadioButton
时,它会使当前RadioButton
可见。这必须以本地风格完成,因为我们需要将ElementName
传递给Binding
。因此,当RadioButton
被检查时,它会折叠并使另一个RadioButton
可见。你还会注意到我默认选中了我想要隐藏的按钮。显然,你可以用绑定来连接它。
类似的方法可以应用于常规按钮:
预览强>
<强>代码:强>
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type Button}" x:Key="ToggleButtonStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="CancelButton" Content="Cancel">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ToggleButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=BackButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button x:Name="BackButton" Content="Back">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ToggleButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=CancelButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Window>
此处,我正在与IsChecked
合作,而不是IsFocused
。您可以通过使用EventTrigger
和Click
事件来完成类似的事情......但是,还有更多工作要做。 IsPressed
可能看起来像是一个很好的候选人,但问题是,一旦按下按钮,另一个几乎会瞬间出现,并且IsPressed
几乎会立即设置为true
。所以,你最终会发现这种循环行为,似乎没有任何事情发生。请注意,我使用Grid
将这些按钮放在彼此的顶部,默认情况下我希望在顶部显示这个按钮,这样我就不必担心默认的可见性或焦点。但是,您可以使用任何其他面板,只需将您要隐藏的按钮的Visibility
默认设置为Collapsed
。
如果您不想使用多个控件(在这种情况下为两个按钮),您还可以根据Content
的条件设置按钮的DataTrigger
属性以显示不同的文本。您只需确保正确处理Command
。
答案 1 :(得分:3)
由于您要求仅使用XAML方法在基于ViewModel属性的内容控件中切换按钮,具体如何:
首先定义按钮样式以将两个按钮路由到同一事件:
<Style x:Key="buttonClickButton" TargetType="Button">
<EventSetter Event="Click" Handler="Button_Click"/>
</Style>
然后使用数据触发器定义内容控件样式,根据名为“IsCancelButton”(bool)的ViewModel属性切换内容:
<Style x:Key="ButtonSwitchContentCtrl" TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding IsCancelButton}" Value="True">
<Setter Property="Content">
<Setter.Value>
<Button x:Name="CancelButton" Style="{StaticResource buttonClickButton}"
HorizontalAlignment="Left" VerticalAlignment="Top"
Width="80" Height="80" IsCancel="True" Content="Cancel Button" BorderBrush="Black" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsCancelButton}" Value="False">
<Setter Property="Content">
<Setter.Value>
<Button x:Name="GoBackButton" Style="{StaticResource buttonClickButton}"
HorizontalAlignment="Left" VerticalAlignment="Top"
Width="80" Height="80" IsCancel="True" Content="Go Back Button" BorderBrush="Black" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
然后让你的按钮显示如下:
<ContentControl Style="{StaticResource ButtonSwitchContentCtrl}"/>
答案 2 :(得分:1)
您可以使用一个Button(例如在XAML中声明为Name="btnCancel"
)和使用Lambda样式事件订阅的C#代码隐藏中的简单代码片段来实现此类功能,如:
btnCancel.Click+=(s,e)=>{
if (btnCancel.Text=="Cancel")
{
// SOME CODE CORRESPONDING TO "CANCEL" CLICK EVENT
btnCancel.Text ="GoBack"
}
else
{
// CORRESPONDING TO "GoBack" CLICK EVENT
btnCancel.Text ="Cancel"
}
}
如果您想在Button上使用某些图形内容(图像),请使用该Button的Tag
属性而不是Text
,并以编程方式在图像之间切换。
结合其他注意事项:您所描述的业务逻辑可以使用DataTriggers
在XAML中实现(正如其他人所做的那样),但不是为2-Buttons解决方案编写大量的XAML,而是实现一个单按钮解决方案,可以像这样,也可以使用.NET ToggleButton
Class(re:https://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.togglebutton%28v=vs.110%29.aspx);另外,它可能是一个CheckBox
控件,只是风格正确。
无论如何,除了改变Button的可视状态之外,你很可能还需要事件处理程序来完成一些实际的工作,这样紧凑的Lambda风格的事件订阅会很方便。
希望这可能会有所帮助。最好的问候,