WPF enlaces de datos de árbol y estilos de menú

prefacio

En el desarrollo de WPF, a menudo utilizado para Menú y ContentMenu. Pero el estilo nativo de relativamente simple, relativamente consecución de una mejor interfaz para la gente que es muy desagradable. Por lo tanto, lo que se relaciona con el estilo de menú cambiado. Al mismo tiempo, también queremos Menú automática La unión a la vista del modelo de datos, los datos se inicia automáticamente elemento MenuItem. A continuación hacemos una implementación sencilla de estas ideas.

Ver modelo

Suponemos que los elementos del menú se describen en el texto y la intención de la necesidad de mostrar imágenes en miniatura. Por lo tanto tenemos que tener los nombres y atributos de la ruta de la imagen allí. Adicional, necesaria para almacenar un conjunto de subclave niños, para formar un conjunto de datos de árboles.

Ver Clase Modelo

public class CommonTreeModel
{
    /// <summary>
    /// 名字
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 图片的路径
    /// </summary>
    public string IconPath { get; set; }
    /// <summary>
    /// 子项
    /// </summary>
    public ObservableCollection<CommonTreeModel> Children { get; set; }
}

simulacro de datos

Hemos utilizado Bogusse generaron datos de simulación. Uso Nuget buscar Bogus añadir a.

/// <summary>
/// 菜单项数据集,前端将binding到该属性上
/// </summary>
public ObservableCollection<CommonTreeModel> MenuTreeSource { get; set; }

private void InitData()
{
    var general = new Bogus.Faker<CommonTreeModel>()
        .RuleFor(t => t.Name, t => t.Commerce.Product())//名字:商业产品
        .RuleFor(t => t.IconPath, t => t.Image.LoremFlickrUrl(32, 32));//图片:使用LoremFlick网站的图片
    var rd = new Random(DateTime.Now.Millisecond);//随机数
    MenuTreeSource = GenerateTreeData(general, rd, 10, 3, 10);
}

private ObservableCollection<CommonTreeModel> GenerateTreeData(Faker<CommonTreeModel> faker, Random rd, int topCount, int subMin, int subMaxm, int level = 0, int levelLimit = 4)
{
    var list = new ObservableCollection<CommonTreeModel>(faker.Generate(level == 0 ? topCount : rd.Next(subMin, subMaxm)));
    level++;
    if (level < levelLimit)
    {
        foreach (var item in list)
        {
            if (rd.Next() % 2 == 0)
            {
                item.Children = GenerateTreeData(faker, rd, topCount, subMin, subMaxm, level, levelLimit);
            }
        }
    }
    return list;
}

Aquí, generamos el nivel máximo posible, como un árbol 4: MenuTreeSource.

En WPF Menú

Menú de escritura front-end Vamos con destino a los datos.

<Menu ItemsSource="{Binding MenuTreeSource}" HorizontalAlignment="Center">
    <Menu.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <Label Content="{Binding Name}"></Label>
        </HierarchicalDataTemplate>
    </Menu.ItemTemplate>
</Menu>

El estilo original de la pantalla los siguientes efectos, un total de cuatro, y la primera etapa y después de tres inconsistente.

Sólo tenemos que reescribir estilo Menultem, el menú se puede cambiar para mostrar el efecto de:

<Style TargetType="MenuItem">
    <Setter Property="FontSize" Value="20"></Setter>
    <Setter Property="Foreground" Value="#b8d00a"></Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid>
                    <Grid.Style>
                        <Style TargetType="Grid">
                            <Setter Property="Background" Value="#b8d00a"/>
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="#f46a56"></Setter>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Grid.Style>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="auto"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                        <ColumnDefinition Width="auto"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Image Width="32" Height="32" Margin="5" Source="{Binding IconPath}" />
                    <Label Content="{Binding Name}" Margin="10 0" Grid.Column="1" VerticalContentAlignment="Center"/>
                    <Label Name="MoreLbl" Content=">>" Grid.Column="2" VerticalContentAlignment="Center">
                        <Label.Style>
                            <Style TargetType="Label">
                                <Setter Property="Visibility" Value="Visible"></Setter>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Children}" Value="{x:Null}">
                                        <Setter Property="Visibility" Value="Collapsed"></Setter>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Label.Style>
                    </Label>
                    <Popup AllowsTransparency="True"
                        IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
                        Placement="Right" x:Name="SubMenuPopup" Focusable="false">
                        <Border x:Name="SubMenuBorder"  BorderThickness="1" BorderBrush="Black">
                            <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
                        </Border>
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Los controles Popupson representativos de los elementos del menú infantil. En la que StackPanella IsItemsHost="True"garantía de correcta manipulación de los niños.

Llamado MoreLbl control de la etiqueta se utiliza para solicitar si tener hijos. >> aquí con un breve vistazo a la identidad, el lector puede imaginar control de la trayectoria de imagen o hacer un hermoso estilo.

Los resultados finales son las siguientes, primaria y secundaria todavía no está unificada.

Menú unificado primaria y secundaria

Por la unidad que necesitamos para ajustarse al estilo de menú. La forma más fácil es realizar un reemplazo de contenedores sub elementos, nos StackPanelcontrolamos, y ordenar los contenidos expuestos a la dirección vertical.

<Menu ItemsSource="{Binding MenuTreeSource}" HorizontalAlignment="Center">
    <Menu.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical"></StackPanel>
        </ItemsPanelTemplate>
    </Menu.ItemsPanel>
    <Menu.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}"></HierarchicalDataTemplate>
    </Menu.ItemTemplate>
</Menu>

Los resultados finales son las siguientes:

ContextMenu en los controles de WPF

Menú y ContextMenu diferente, ya que puede hacer clic derecho emergente muchas formas de controles del menú pop-up, como el cuadro de lista, etiquetas, cuadrícula y otros contenidos del menú son posibles, necesitamos el botón derecho del ratón se puede expulsarla.

Utilizamos Labelun ejemplo sencillo:

<Label Content="鼠标右键弹出ContextMenu" HorizontalAlignment="Center"HorizontalContentAlignment="Center" FontSize="25" Background="#221a12"Foreground="#b8d00a"
     MouseDown="Label_MouseDown">
    <Label.ContextMenu>
        <ContextMenu ItemsSource="{Binding MenuTreeSource}">
            <ContextMenu.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}" />
            </ContextMenu.ItemTemplate>
        </ContextMenu>
    </Label.ContextMenu>
</Label>

Antes de estilos son de estilo global, utilizará automáticamente el valor predeterminado. Los resultados son los siguientes:

Capaz de encontrar un estilo es ligeramente diferente, tenemos que cambiar ContextMenuel estilo

<Style TargetType="{x:Type ContextMenu}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Setter Property="Grid.IsSharedSizeScope" Value="true"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">
                <Border 
                    BorderBrush="Black"
                    BorderThickness="1" >
                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Plantilla simple puede ser reescrito.

resumen

Aquí solamente una breve introducción sobre cómo volver a escribir una plantilla de estilo para cambiar el efecto pantalla del menú. En particular, tenemos que utilizar mejor aspecto resultados, diseñar su propio. Los usos del marco del proyecto de WPF dotNET versión core3.1. En el trabajo agrícola debe ser el mismo.

Supongo que te gusta

Origin www.cnblogs.com/hsxian/p/12521501.html
Recomendado
Clasificación