简介
TabControl控制带来允许你创建一组标签的灵活性,您的网站导航可以用来组织网页内容。
背景
TabControl的是Silverlight工具包控制,所以首先你要安装最新{A1} NBSP工具包下载。安装工具包之后,你会看到TabControl的在您toolbox.nbsp; 在Silverlight的开发环境,它很难布局TabControl.nbsp;有时候我们不得不要求定制我们的选项卡控件的布局,所以我们需要创建自定义模板TabControl和TabItems.nbsp;在这篇文章中,我们走过怎样创建TabControl的边栏右侧的侧边栏控制和显示/隐藏侧酒吧。使用代码 第1步:创建为侧barnbsp自ScalePanel控制; ScalePanel.csnbsp;
在这段代码中,你注意到ScaleXPropertyScaleYProperty依赖属性定义。因此,我们出现的问题什么是DepenencyProperty的吗?为什么我们需要使用。我给你简要说明了解有关DepenencyProperty。DependencyProperty的像任何依赖项属性其他财产,但可以保持默认值,建机制属性更改属性值验证和自动通知值(属性值 - 特别是UI的人听)和任何在Silverlight中绑定是绑定到一个依赖Property.nbsp;依赖项属性与Silverlight属性系统注册属性通过调用在DependencyProperty.Register的方法。 依赖的目的属性是提供一种方法来计算的属性值的基础上,其他投入的价值。 DependencyObject的定义可以注册并拥有一个依赖项属性的基类。你可以进入详细例如,请点击此链接。{A2的}NBSP,所以双方的scaleY和scaleY属性缩放面板content.nbsp;有两个覆盖方法定义,一个是MeasureOverride和另一种是ArrangeOverride。 public class ScalePanel : Panel
{
#region ScaleXProperty
public Double ScaleX
{
get { return (Double)GetValue(ScaleXProperty); }
set { SetValue(ScaleXProperty, value); }
}
public static readonly DependencyProperty ScaleXProperty =
DependencyProperty.Register("ScaleX", typeof(Double), typeof(ScalePanel), new PropertyMetadata(1.0d, new PropertyChangedCallback(ScaleXChanged)));
public static void ScaleXChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ScalePanel obj = sender as ScalePanel;
if (obj != null)
{
obj.OnScaleXChanged(e);
}
}
private void OnScaleXChanged(DependencyPropertyChangedEventArgs e)
{
InvalidateMeasure();
}
#endregion
#region ScaleYProperty
public Double ScaleY
{
get { return (Double)GetValue(ScaleYProperty); }
set { SetValue(ScaleYProperty, value); }
}
public static readonly DependencyProperty ScaleYProperty =
DependencyProperty.Register("ScaleY", typeof(Double), typeof(ScalePanel), new PropertyMetadata(1.0d, new PropertyChangedCallback(ScaleYChanged)));
public static void ScaleYChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ScalePanel obj = sender as ScalePanel;
if (obj != null)
{
obj.OnScaleYChanged(e);
}
}
private void OnScaleYChanged(DependencyPropertyChangedEventArgs e)
{
InvalidateMeasure();
}
#endregion
protected override Size MeasureOverride(Size availableSize)
{
Size finalSize = new Size();
if (Children.Any())
{
UIElement child = Children.First();
child.Measure(availableSize);
finalSize.Width = Math.Min(child.DesiredSize.Width, availableSize.Width);
finalSize.Height = Math.Min(child.DesiredSize.Height, availableSize.Height);
}
finalSize.Width = finalSize.Width * ScaleX;
finalSize.Height = finalSize.Height * ScaleY;
return finalSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
if (Children.Any())
{
UIElement child = Children.First();
child.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
}
return finalSize;
}
}
的MeasureOverride提供的行为通Silverlight的布置。方法措施都有一个默认实施,执行内置在大多数的Silverlight FrameworkElement的布局类。所以
在我们的代码自定义自定义面板的测量通逻辑它和实施执行以下任务:
NBSP。NBSP 1。
遍历儿童。 2.nbsp;对于每一个孩子,调用的测试,使用面积是有道理的基础上面板逻辑如何对待thenbsp子女数和自身的已知大小的限制
NBSP 3。 返回其大小(决定了它需要在布局,根据其计算的子对象分配大小),您可以进入详细榜样本linknbsp; {A3的}ArrangeOverride
提供Silverlight的布局安排合格的行为。
简单安排FrameworkElement的内容。
ArrangeOverride定制排列通
1.Iterates以上的儿童。
2.For每个孩子,要求安排,使用一个Rect其中身高和宽度基于DesiredSize和X和Y基于逻辑是具体到面板上。
3.Returns其大小(即实际大小使用后,该元素在布局安排)
的Silverlight / WPF中,由哪些元素的大小和定位技术布局分为两个步骤:测量通,然后排列pass.You可以细讲例如按照此链接{A4}
步骤2:在您的UserControl添加命名空间。{A5的}{C} 1。 System.windows.Interactivity提供控制执行事件fire.nbsp行动的事件触发器;
2.Interaction提供与EventTrigger的ControlStoryboardAction。 NBSP 3。工具包用于变换的Control.nbsp的布局;步骤3:创建模板的TabItem的。
上述控制模板提供为TabItems.nbsp风格和模板;VisualStateManager来管理国家和逻辑控制状态之间的转换。 创建customStates的,它定义
鼠标悬停,正常和选定为每个TabItmes的VisualState对象。当用户把鼠标在标签项目,其背景颜色更改为黄色和对小鼠离开它会回红色color.nbsp; <ControlTemplate x:Key="RightMenuTabItem"
TargetType="sdk:TabItem">
<Border>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TabHeaderHighlightBackgroundBorder"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.25" />
<ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
Storyboard.TargetName="ContControl"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Color>Black</Color>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
Storyboard.TargetName="TabHeaderBackgroundBorder"
Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Thickness>1 1 0 0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TabHeaderSelectedBackgroundBorder"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.25" />
<ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
Storyboard.TargetName="ContControl"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Color>Black</Color>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
Storyboard.TargetName="TabHeaderBackgroundBorder"
Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Thickness>1 1 0 0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<toolkit:LayoutTransformer x:Name="layoutTransformer">
<toolkit:LayoutTransformer.LayoutTransform>
<RotateTransform Angle="90" />
</toolkit:LayoutTransformer.LayoutTransform>
<Border x:Name="TabHeaderBackgroundBorder"
RenderTransformOrigin="0.5,0.5"
BorderBrush="Black"
BorderThickness="1,1,0,1"
Background="{StaticResource TabHeaderBackground}">
<Grid>
<Border x:Name="TabHeaderHighlightBackgroundBorder"
Opacity="0"
Background="{StaticResource TabHeaderHighlightBackground}" />
<Border x:Name="TabHeaderSelectedBackgroundBorder"
Opacity="0"
Background="{StaticResource TabHeaderSelectedBackground}" />
<ContentControl Content="{TemplateBinding Header}"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Margin="16,10,16,10"
FontFamily="Verdana"
FontSize="15"
Foreground="White"
FontWeight="Bold"
Cursor="Hand"
x:Name="ContControl" />
</Grid>
</Border>
</toolkit:LayoutTransformer>
</Border>
</ControlTemplate>
{补体C3}上面的片段旋转从横向Vertiacal.nbsp TabItems的;第4步:创建模板TabControl的。{的C4}在上面的ControlTemplate创建多边形按钮
TabControl的背景设置显示/隐藏面板(边栏)和风格GradientColor.nbsp;创建一个侧栏控制和故事情节为animation.on点击按钮触发,执行触发显示/隐藏侧边栏用的DoubleAnimation。
{碳五}此代码描述动画scalepanel,并设置宽度从300到0
NBSP。;第5步:拖动放;拖放到页面的TabControl。{5233}
上面的代码,运用样式和模板TabControl和TabItems
NBSP第6步:切换到ViewModel的,创建HeaderViewModel"
NBSP。;对于通知在变化的属性,下载Silverlight.Extensions.dll从{A6的},并添加到您的项目的参考。它将添加VieModelBase类其中从继承INotifyPropertyChanged的propertyChangeNotification。VieModelBase类增加为RegisterPropertyChangeCallback和进程的子element.HeaderViewModel.csnbsp的方法;
在上面的类创建标头属性设置上TabItems的头。SETP 7:创建ViewModels每个TabItems。 DepartmentViewModel.csnbsp;{C8的}在上面的代码创建,署类,它定义NBSP包装;从部门级性能,并提高财产,通知查看变化。为雇员和产品类别,以相同的方式创建的ViewModel绑定到view.nbsp的性质;第8步:创建TabPropertiesViewModel持有所有viewmodels添加到项目collection.TabPropertiesViewModel.csnbsp;
创建每个视图模型的属性。我已装箱HeaderViewModel收集,因为它是所有视图模型的基类。在类的构造函数,创建每个视图模型的实例和addednbsp;到项目collection.nbsp; 第9步:创建视图ViewModel的。DepartmentView.xamlEmployeeView.xamlProductView.xaml在上述三个视图绑定视图模型属性查看。TabPropertiesView.xaml{C10的}地方SideMenuControl.xamlnbsp;成加入参考UserControl的(即的xmlns:控制="CLR命名空间:SideMenuTabControl.Controlsquot ;)和绑定的ItemsSource ViewModel.nbsp; 第10步:绑定TabItes到SideMenuControl.SideMenuControl.xaml.csnbsp TabControl的;{C11的}在上面的代码中,我已经创建DepenencyProperty FOT的ItemsSource类型是收集的IEnumerable.nbsp; IEnumerablenbsp;NET Framework提供了IEnumerable和IEnumerator接口实施类似行为,以用户定义的类的集合。开发人员可以实现这些接口,收集他们提供类似的行为类。IEnumerable接口包含一个抽象成员函数的GetEnumerator()并返回一个接口IEnumerator任何成功调用。这的IEnumerator接口将允许我们来遍历任何定制collection.nbsp之;IEnumerablelt; TGT;接口是一个通用的接口,提供了一个抽象的多元素循环。我已经书面BuildItemsSource方法返回集合viewmodels和它的返回类型是IEnumerable。 public class TabPropertiesViewModel : ViewModelBase
{
private DepartmentViewModel _departmentViewModel;
public DepartmentViewModel DepartmentViewModel
{
get { return _departmentViewModel; }
set
{
_departmentViewModel = value;
RaisePropertyChanged(() => DepartmentViewModel);
}
}
private EmployeeViewModel _employeeViewModel;
public EmployeeViewModel EmployeeViewModel
{
get { return _employeeViewModel; }
set
{
_employeeViewModel = value;
RaisePropertyChanged(() => EmployeeViewModel);
}
}
private ProductViewModel _productViewModel;
public ProductViewModel ProductViewModel
{
get { return _productViewModel; }
set
{
_productViewModel = value;
RaisePropertyChanged(() => ProductViewModel);
}
}
public ObservableCollection<HeaderViewModel> Items { get; set; }
public TabPropertiesViewModel()
{
DepartmentViewModel = ProcessChild(new DepartmentViewModel());
EmployeeViewModel = ProcessChild(new EmployeeViewModel());
ProductViewModel = ProcessChild(new ProductViewModel());
Items = new ObservableCollection<HeaderViewModel>{
DepartmentViewModel,
EmployeeViewModel,
ProductViewModel,
};
}
}
我已经使用了产量关键字返回枚举器对象。
产量yield关键字用于在迭代器块,以提供一个值枚举器对象或迭代结束信号。使用的问题时表达式求值和枚举器对象的值返回。yield关键字的编译器的信号出现的方法,它是一个迭代器块。编译器生成一个类来实现的行为,表示在迭代阻塞。在迭代器块,产量关键字return关键字一起使用,提供枚举器对象的值。这是返回的值。yield语句不能出现在一个匿名方法。我已经写为MenuItemsTabControl SizeChange事件处理程序提供用户维持的TabItems选定的索引,当用户显示/隐藏sidebar.nbsp;