WPF滚动菜单

时间:2013-06-07 02:58:30

标签: wpf xaml .net-4.0

我想制作一个像Windows Media Center的音乐库界面的WPF菜单结构。基本上,前提是有一个类别和项目列表。您可以使用向左/向右箭头键滚动类别。可用类别在屏幕上“换行”,列表中的第二项始终是所选类别。该类别的可用项目位于类别下方的列表中。当您在类别中时,可以按向下箭头导航到列表,这样做会导致上面的类别“删除”字体大小并淡出一点点,并且列表项会弹出字体大小和淡入淡出有点儿。在项目列表中,您现在可以向左,向右,向上,向下导航项目。如果按下最上面一行的项目,您将返回到类别列表中,并使其弹出字体大小,并且项目会弹出字体大小。

我是WPF总裁...任何指导都会受到赞赏。

最好的例子是尝试WMC音乐库界面 - 但对于那些没有安装它的人,我已经包含了几个屏幕截图:

WMC Category Navigation WMC Item Navigation

1 个答案:

答案 0 :(得分:2)

我做了一些事情:

enter image description here

对于基础我采用元素 TabControl ,通过你的截图他是最合适的。此外,它可能是一个TabItem任何控件(如 DataGrid )。首先,您需要在TabItem中添加导航箭头(它表示一个类别),并且需要隐藏未选中的TabItem。要正确执行,您需要在TabItem(App.xaml)模板中执行此操作:

    <Style x:Key="{x:Type TabItem}" TargetType="{x:Type TabItem}">
        <Setter Property="OverridesDefaultStyle" Value="True" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Foreground" Value="Gray" />
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="MinHeight" Value="20" />
        <Setter Property="MinWidth" Value="120" />
        <Setter Property="FontFamily" Value="./#Segoe UI" />
        <Setter Property="FontSize" Value="14" />
        <Setter Property="FontWeight" Value="Normal" />            
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Border SnapsToDevicePixels="True" Name="Border" Margin="0,0,2,0" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0">
                        <Grid>
                            <!-- There are arrow Prev and Next -->
                            <Button Name="PrevButton" Style="{StaticResource PrevButton}" />
                            <ContentPresenter Name="ContentSite" HorizontalAlignment="Center" Margin="5" VerticalAlignment="Center" RecognizesAccessKey="True" ContentSource="Header" />
                            <Button Name="NextButton" Style="{StaticResource NextButton}" />
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="TabStripPlacement" Value="Bottom">
                            <Setter TargetName="Border" Property="CornerRadius" Value="0" />
                        </Trigger>

                        <Trigger Property="TabStripPlacement" Value="Left">
                            <Setter TargetName="Border" Property="CornerRadius" Value="0" />
                        </Trigger>

                        <!-- Here is hiding the arrows -->
                        <Trigger Property="IsSelected" Value="False">
                            <Setter TargetName="PrevButton" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="NextButton" Property="Visibility" Value="Collapsed" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="#F4F4F4" />
                <Setter Property="Foreground" Value="Black" />
                <Setter Property="FontSize" Value="16" />
            </Trigger>

            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Background" Value="Black" />
                <Setter Property="Foreground" Value="White" />
            </Trigger>
        </Style.Triggers>
    </Style>

箭头按钮样式(App.xaml):

    <!-- Prev button style -->
    <Style x:Key="PrevButton" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="Margin" Value="3,0,0,0" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="ToolTip" Value="Prev" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Background="{TemplateBinding Background}">
                        <Grid>
                            <ContentPresenter RecognizesAccessKey="True" />
                            <Path x:Name="PrevButton" SnapsToDevicePixels="True" Width="13" Height="16" Stretch="Fill" Fill="Gray" Data="F1 M 35.8724,37.6042L 39.0391,40.7708L 50.5182,51.8542L 40.2266,51.8542L 25.1849,37.6041L 40.2266,23.3542L 50.5182,23.3542L 39.0391,34.4375L 35.8724,37.6042 Z " />
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="PrevButton" Property="Fill" Value="Black" />
                        </Trigger>

                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="PrevButton" Property="Fill" Value="Green" />
                        </Trigger>

                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Opacity" Value="0.6" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Next button style -->
    <Style x:Key="NextButton" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="HorizontalAlignment" Value="Right" />
        <Setter Property="Margin" Value="0,0,3,0" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="ToolTip" Value="Next" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Background="{TemplateBinding Background}">
                        <Grid>
                            <ContentPresenter RecognizesAccessKey="True" />
                            <Path x:Name="NextButton" SnapsToDevicePixels="True" Width="13" Height="16" Stretch="Fill" Fill="Gray" Data="F1 M 39.8307,37.6042L 36.6641,34.4375L 25.1849,23.3542L 35.4766,23.3542L 50.5182,37.6042L 35.4766,51.8542L 25.1849,51.8542L 36.6641,40.7708L 39.8307,37.6042 Z " />
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="NextButton" Property="Fill" Value="Black" />
                        </Trigger>

                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="NextButton" Property="Fill" Value="Green" />
                        </Trigger>

                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Opacity" Value="0.6" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

主窗口XAML:

        

    <TabControl Name="SampleTabControl" HorizontalAlignment="Right" Loaded="TabControl_Loaded">
        <TabItem Name="Soccer" Header="Soccer">
            <ListBox Name="SoccerListBox" BorderBrush="Transparent" BorderThickness="0">
                <ListBoxItem>Player name: Ronaldo</ListBoxItem>
                <ListBoxItem>Player name: Messi</ListBoxItem>
                <ListBoxItem>Player name: Sergio Ramos</ListBoxItem>
                <ListBoxItem>Player name: Puyol</ListBoxItem>
            </ListBox>
        </TabItem>

        <TabItem Name="Hockey" Header="Hockey">
            <ListBox Name="HockeyListBox" BorderThickness="0">
                <ListBoxItem>Player name: Cal Heeter</ListBoxItem>
                <ListBoxItem>Player name: Jeff Petry</ListBoxItem>
                <ListBoxItem>Player name: Erik Johnson</ListBoxItem>
                <ListBoxItem>Player name: Matt Hunwick</ListBoxItem>
            </ListBox>
        </TabItem>

        <TabItem Name="Basketbol" Header="Basketbol">
            <ListBox Name="BasketbolListBox" BorderThickness="0">
                <ListBoxItem>Player name: Kobe Bryant</ListBoxItem>
                <ListBoxItem>Player name: Chris Paul</ListBoxItem>
                <ListBoxItem>Player name: Carmelo Anthony</ListBoxItem>
                <ListBoxItem>Player name: LeBron James</ListBoxItem>
            </ListBox>
        </TabItem>

        <TabItem Name="Baseball" Header="Baseball">
            <ListBox Name="BaseballListBox" BorderThickness="0">
                <ListBoxItem>Player name: Ralph Kiner</ListBoxItem>
                <ListBoxItem>Player name: Dizzy Dean</ListBoxItem>
                <ListBoxItem>Player name: Duke Snider</ListBoxItem>
                <ListBoxItem>Player name: Ozzie Smith</ListBoxItem>
            </ListBox>
        </TabItem>
    </TabControl>

现在你需要制作一个功能性箭头工人。为此,请创建一个 TabControl_Loaded 事件,从模板中找到按钮,并将它们分配给事件处理程序:

    private void TabControl_Loaded(object sender, RoutedEventArgs e)
    {
        var items = SampleTabControl.Items;

        foreach (TabItem item in items)
        {
            Button MyPrevButton = (Button)item.Template.FindName("PrevButton", item);
            Button MyNextButton = (Button)item.Template.FindName("NextButton", item);

            MyPrevButton.Click += new RoutedEventHandler(MyPrevButton_Click);
            MyNextButton.Click += new RoutedEventHandler(MyNextButton_Click);
        }
    }

事件处理程序:

    private void MyPrevButton_Click(object sender, RoutedEventArgs e)
    {
        NavigationTabItem(SampleTabControl, "Prev", 1);
    }

    private void MyNextButton_Click(object sender, RoutedEventArgs e)
    {
        NavigationTabItem(SampleTabControl, "Next", 1);
    }

为了便于导航,创建了功能:

    private void NavigationTabItem(TabControl MyTabControl, string Direction, int Num) 
    {
        if (Direction == "Prev")
        {
            MyTabControl.SelectedIndex -= Num;
        }

        if (Direction == "Next")
        {
            MyTabControl.SelectedIndex += Num;
        }
    }

现在我们需要拦截键盘界面。为此,在窗口上创建并安装了处理程序(最好将它安装在TabControl上,当程序开始将它放在焦点上时):

<Window ... KeyDown="SampleTabControl_KeyDown">

    private void SampleTabControl_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Down) 
        {
            if (SampleTabControl.SelectedIndex == 0)
            {
                SoccerListBox.Focus();
            }

            if (SampleTabControl.SelectedIndex == 1)
            {
                HockeyListBox.Focus();
            }

            if (SampleTabControl.SelectedIndex == 2)
            {
                BasketbolListBox.Focus();
            }

            if (SampleTabControl.SelectedIndex == 3)
            {
                BaseballListBox.Focus();
            }
        }

        if (e.Key == Key.Left)
        {
            NavigationTabItem(SampleTabControl, "Prev", 1);
        }

        if (e.Key == Key.Right)
        {
            NavigationTabItem(SampleTabControl, "Next", 1);
        }
    }

可选设置为在ListBoxItem和TabItem上选择动画。