在WPF中应用条件样式

3

我遇到了一个问题,需要在菜单项上应用条件样式,这里是我代码片段的一部分:

<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,10,0,0">
    <Menu HorizontalAlignment="Left" KeyboardNavigation.TabNavigation="Once" Background="Transparent" d:LayoutOverrides="Height">
        <MenuItem Header="Menu1" Style="{DynamicResource M_Left}"  />
        <MenuItem Header="Menu2" Style="{DynamicResource M_Middle}" />
        <MenuItem Header="Menu3" Style="{DynamicResource M_Right}" Visibility="{Binding IsEligibleToDisplay, Converter={StaticResource MyVisibilityConverter}}" />
    </Menu>
</Grid>

在上面的代码中,“IsEligibleToDisplay”是一个布尔属性,而“MyVisibilityConverter”则根据其值为True或False将Visibility设置为Visible或Hidden。
希望实现的效果是:如果“Menu3”的可见性是Hidden,也就是说“IsEligibleToDisplay”等于false,则“Menu2”的样式应该是Style=”{DynamicResource M_Right}”,反之,则样式应该是Style=”{DynamicResource M_Middle}”。
代码示例(仅供参考,语法可能有误):
<MenuItem Header="Menu2" Style="IsEligibleToDisplay ? {DynamicResource M_Middle} : {DynamicResource M_Right}" />  

任何帮助都将不胜感激!
3个回答

7

如果您的要求只是使用XAML,那么我想您可以使用DataTriggers

您无法直接在Style属性中设置您的“条件”,而是必须将其移动到Style声明内部。

也许这个小示例可以帮助您解决问题:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="400">

    <Window.Resources>

        <Style x:Key="ConditionalStyle" TargetType="MenuItem">
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=Menu3, Path=Visibility}" Value="Visible">
                    <Setter Property="Foreground" Value="Red" />
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=Menu3, Path=Visibility}" Value="Hidden">
                    <Setter Property="Foreground" Value="Green" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>


    <StackPanel>
        <Menu HorizontalAlignment="Left" KeyboardNavigation.TabNavigation="Once" Background="Transparent">
            <MenuItem Header="Menu1" />
            <MenuItem Header="Menu2" Style="{DynamicResource ConditionalStyle}" />
            <MenuItem Name="Menu3" Header="Menu3" Visibility="Visible" />
        </Menu>

        <Button Content="ClickMe" Margin="10" Click="Button_Click" />
    </StackPanel>
</Window>

我使用按钮来切换菜单3的可见性。我使用了一个简单的处理程序:

private void Button_Click(object sender, RoutedEventArgs e)
{
    if(Menu3.Visibility == System.Windows.Visibility.Visible)
    {
        Menu3.Visibility = System.Windows.Visibility.Hidden;
        return;
    }
    Menu3.Visibility = System.Windows.Visibility.Visible;
}

我希望这个解决方案适合您。


感谢您提供代码片段。不幸的是,这不是我需要的。请阅读我的问题。可见性运作良好,我需要设置样式M_Right或M_Middle。 - Gaurav Arora
@GauravKumarArora,我不知道你是如何声明M_Right和M_Middle样式的,因此我用两个简单的setter替换了它们来改变前景色。我的代码片段只是一个提示,但是你可以将我的setter替换为你真正的样式所属的setter。无论如何,如果你愿意,只需发布你的样式,我就会在我的帖子中进行编辑。 - Il Vic
感谢您,让我试一试,如果我从以上任何答案中找到解决方案,我会将其标记为最佳答案。 - Gaurav Arora
@GauravKumarArora,我将触发器绑定到可见性属性,因为我没有你的ViewModel,但当然你可以直接将它们绑定到你的“IsEligibleToDisplay”属性。 - Il Vic

2
您可能想考虑的一种方法是,在菜单控件上使用ItemContainerStyleSelector属性来使用样式选择器。

ItemContainerStyleSelector Property

这将允许您创建自定义逻辑,以设置所需的样式在每个菜单项上。

感谢您的及时回复。要求是在XAML页面中使用条件语句,我相信您所建议的需要在cs文件中添加一些逻辑。如果您有关于我的上述代码的示例代码,我将不胜感激。 - Gaurav Arora

1
也许你可以尝试使用基于IsEligibleToDisplay属性的数据触发器,并使用通用模板。将这个例子放在ResourceDictionary中:
        <!-- The visibility converter -->
        <BooleanToVisibilityConverter x:Key="MyVisibilityConverter" />

        <!-- Common template -->
        <ControlTemplate x:Key="myContent">
            <Label Content="{Binding Header, RelativeSource={RelativeSource TemplatedParent}}" 
                       HorizontalAlignment="Center"
                       HorizontalContentAlignment="Center"
                      Padding="0"
                       Height="20" 
                       Width="80" 
                       Background="Green"/>

        </ControlTemplate>

        <!-- M_Left style -->
        <Style x:Key="M_Left"
               TargetType="MenuItem">
            <Setter Property="Background"
                    Value="Yellow" />
        </Style>

        <Style x:Key="M_Middle"
               TargetType="MenuItem">
            <Setter Property="Background"
                    Value="Red" />
            <Style.Triggers>
                <!-- trigger based on IsEligibleToDisplay property -->
                <DataTrigger Binding="{Binding IsEligibleToDisplay}"
                             Value="false">
                    <!-- If false then apply common template to middle menu item. -->
                    <Setter Property="Template"
                            Value="{DynamicResource myContent}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="M_Right"
               TargetType="MenuItem">
            <Setter Property="Template"
                    Value="{DynamicResource myContent}" />
        </Style>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接