Статьи

Исследование панели инструментов Silverlight

В этом посте я объясняю, как создать базовую панель инструментов в Silverlight. Эта панель инструментов состоит из двух частей

  •  
    • Панель инструментов
    • Элемент панели инструментов

Снимок экрана

образ

Панель инструментов панели

Этот пользовательский элемент управления содержит все элементы панели инструментов. Этот элемент управления внутренне использует Stackpanel для организации элементов панели инструментов. Ниже XAML и код позади

XAML

<UserControl x:Class="Controls.ToolBarPanel"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
             Background="Transparent"
    d:DesignHeight="300" d:DesignWidth="400">
    
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <StackPanel x:Name="itemHolder" Orientation="{Binding Orientation}" Background="Transparent"></StackPanel>
    </Grid>
</UserControl>

Код позади

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Controls
{
    public partial class ToolBarPanel : UserControl
    {
        public event Click ToolBarItemClick;
        public ToolBarPanel()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(ToolBarPanel_Loaded);
        }

        void ToolBarPanel_Loaded(object sender, RoutedEventArgs e)
        {
            this.CreateClickEvent();
        }

        public static DependencyProperty ToolBarItemsProperty = DependencyProperty.Register("ToolBarItems",
        typeof(PresentationFrameworkCollection<ToolBarItem>),
        typeof(ToolBarPanel),
        new PropertyMetadata(null));
        public UIElementCollection ToolBarItems
        {
            get 
            {
                return itemHolder.Children;
            }
        }

        public static DependencyProperty ToolBarItemsOrientation = DependencyProperty.Register("Orientation",
        typeof(Orientation),
        typeof(ToolBarPanel),
        new PropertyMetadata(null));
        public Orientation Orientation
        {
            get { return (itemHolder.Orientation); }
            set { itemHolder.Orientation=value; }
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            itemHolder.DataContext = this;
        }

        private void CreateClickEvent()
        {
            foreach (UIElement elem in itemHolder.Children)
            {
                ToolBarItem item = elem as ToolBarItem;
                if(item!=null)
                    item.ToolBarItemClick += new Click(item_ToolBarItemClick);
            }
        }

        void item_ToolBarItemClick(object sender, string key)
        {
            if (ToolBarItemClick != null)
                this.ToolBarItemClick(sender, ((ToolBarItem)sender).ToolBarItemKey);
        }

    }
}

Одно свойство, которое я хотел выделить здесь, это свойство зависимостей ToolbarItems. Это свойство предоставляет доступ к дочернему свойству StackPanels. Пользователи могут добавлять элементы панели инструментов через это свойство. В конце этого поста с примером кода я объясню свойства.

Щелчок делегата, используемый в панели инструментов, объявляется в коде ToolBarItem.

Элемент панели инструментов

Этот элемент управления создает кнопку панели инструментов, она наследуется от элемента управления Button. Чтобы сделать его похожим на кнопку панели инструментов, я изменил шаблон ресурса кнопки. Помимо свойств кнопки по умолчанию добавляется новое свойство, чтобы обеспечить возможность добавления изображения.

XAML

 

<Button x:Class="Controls.ToolBarItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Button.Resources>
        <ControlTemplate x:Key="BtnToolBarItemStyle" TargetType="Button">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Disabled"/>
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border" d:IsOptimized="True"/>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="border">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Thickness>0</Thickness>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderThickness)" Storyboard.TargetName="border">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Thickness>1</Thickness>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                                <ColorAnimation Duration="0" To="#FFF9B167" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="border" d:IsOptimized="True"/>
                                <ColorAnimation Duration="0" To="#FFFFEFB6" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="border" d:IsOptimized="True"/>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.CornerRadius)" Storyboard.TargetName="border">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <CornerRadius>4</CornerRadius>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                                <ColorAnimation Duration="0" To="#FFDEA158" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="border" d:IsOptimized="True"/>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed"/>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Border x:Name="border" BorderBrush="Black" BorderThickness="1" Margin="1,2,2,1" Opacity="0">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="Black" Offset="0"/>
                            <GradientStop Color="White" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                </Border>
                <StackPanel Orientation="Horizontal">
                    <Border x:Name="imgBorder"  BorderBrush="Black" BorderThickness="0" Margin="0" Width="16" Height="16">
                        <Border.Background>
                            <ImageBrush x:Name="imgBorderBrush" Stretch="Fill" ImageSource="{Binding ToolBarItemImage}"/>
                        </Border.Background>
                    </Border>
                    <TextBlock x:Name="caption" Grid.Column="1" TextWrapping="NoWrap" Text="{Binding Content}" FontSize="9.333" TextAlignment="Center" VerticalAlignment="Center" />
                </StackPanel>
            </Grid>
        </ControlTemplate>
    </Button.Resources>

    <Button.Template>
        <StaticResource ResourceKey="BtnToolBarItemStyle"/>
    </Button.Template>
    
</Button>

 

Код позади

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections;
using System.ComponentModel;
namespace Controls
{
    public delegate void Click(object sender, string key);
    public partial class ToolBarItem : Button
    {
        public event Click ToolBarItemClick;
        public ToolBarItem()
        {
            InitializeComponent();
            this.Click += new RoutedEventHandler(ToolBarItem_Click);
        }

        void ToolBarItem_Click(object sender, RoutedEventArgs e)
        {
            if (ToolBarItemClick != null)
                this.ToolBarItemClick(sender, (string)GetValue(ToolBarItemKeyProperty));
        }

        public static DependencyProperty ToolBarItemImageProperty = DependencyProperty.Register("ToolBarItemImage",
        typeof(ImageSource),
        typeof(ToolBarItem),
        new PropertyMetadata(null));
        public ImageSource ToolBarItemImage
        {
            get { return (ImageSource)GetValue(ToolBarItemImageProperty); }
            set { SetValue(ToolBarItemImageProperty, value); }
        }

        public static DependencyProperty ToolBarItemKeyProperty = DependencyProperty.Register("ToolBarItemKey",
        typeof(String),
        typeof(ToolBarItem),
        new PropertyMetadata(null));
        public string ToolBarItemKey
        {
            get { return (string)GetValue(ToolBarItemKeyProperty); }
            set { SetValue(ToolBarItemKeyProperty, value); }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            SetDataContext();
        }
        private void SetDataContext()
        {
            Border border = GetTemplateChild("imgBorder") as Border;
            border.DataContext = this;
            TextBlock txtCaption = GetTemplateChild("caption") as TextBlock;
            txtCaption.DataContext = this;

            if (this.Content == null)
            {
                txtCaption.Margin = new Thickness(0);
                border.Margin = new Thickness(3);
            }
            else
            {
                txtCaption.Margin = new Thickness(3);
            }
        }

    }
}
  • ToolBarItemImage: установить источник изображения для отображения на панели инструментов.

  • ToolBarItemKey: укажите ключ, чтобы определить, какая кнопка нажата.

Тестовая страница

Тестовая страница поможет вам понять, как мы можем использовать этот новый элемент управления

XAML

<controls:ChildWindow x:Class="Popups.TestToolBar"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
           xmlns:tlBar="clr-namespace:EmblemDesigner.Controls" Title="TestToolBar" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="265" d:DesignWidth="432">
    <Grid x:Name="LayoutRoot" Margin="2">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        

        <tlBar:ToolBarPanel Height="50" Background="Transparent" Orientation="Horizontal" ToolBarItemClick="ToolBarPanelExt_ToolBarItemClick" >
            <tlBar:ToolBarPanel.ToolBarItems>
                <tlBar:ToolBarItem Margin="5" ToolBarItemImage="/Ico_Arrow.png"  Content="Arrow" ToolBarItemKey="Arrow"></tlBar:ToolBarItem>
                <tlBar:ToolBarItem Margin="5" ToolBarItemImage="/Ico_Circle.png"   ToolBarItemKey="Circle"></tlBar:ToolBarItem>
            </tlBar:ToolBarPanel.ToolBarItems>
        </tlBar:ToolBarPanel>
        
        <Button x:Name="CancelButton"  Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
        <Button x:Name="OKButton"  Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
    </Grid>
</controls:ChildWindow>

Код позади

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Popups
{
    public partial class TestToolBar : ChildWindow
    {
        public TestToolBar()
        {
            InitializeComponent();
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }


        private void ToolBarPanel_ToolBarItemClick(object sender, string key)
        {
            switch (key)
            {
                case "circle":
                    break;
                case "arrow":
                    break;
            }
        }
    }
}

Если мы прикрепим событие ToolBarItemClick к панели инструментов, оно сгенерирует четный обработчик, как показано выше курсивом. На мероприятии вам предоставят ключ и отправителя. Ключ предоставляет значение, которое мы установили для ToolBarItemKey элемента управления ToolBarItem. На основании ключа мы можем предпринять разные действия. Так как ToolbarItem наследуется от кнопки, вы можете использовать событие нажатия по умолчанию, предоставляемое элементом управления Button.