系列文章目录
WPF自定义控件与样式(1)-矢量字体图标(iconfont)
WPF自定义控件与样式(2)-自定义按钮FButton
WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展
WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式
WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式
WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式
WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu
WPF自定义控件与样式(10)-进度控件ProcessBar自定义样
WPF自定义控件与样式(11)-等待/忙/正在加载状态-控件实现
WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表
WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox
WPF自定义控件与样式(14)-轻量MVVM模式实践
WPF自定义控件与样式(15)-终结篇
一.总结.声明
关于本WPF,本人也只能算是一个刚入门的,在学习中和工作中,学习、借鉴了很多网友的文章和开源的项目的知识。发现提供实际项目开发需要的基础控件、样式的文章大都比较散,不成系列。因此基于现在项目中使用的基础UI库,写了这个系列,希望对有需要的人有所帮助。
本系列包括本文共15篇,就到此为止了。关于一些问题再次说明一下:
- 每一篇文章中都给出了基本所有主要代码,目的仅供参考学习,由于目前还是公司在使用中的项目,因此不便提供完整项目源码,有需要的同学还是多动动手吧!
- 对于确实需要源码参考学的,推荐开源项目MahApps.Metro(http://mahapps.com/),我在那里面学习借鉴了很多,本系列中不少样式中都有她(就是她)的影子。
- 本文会把一些额外遗漏的资源或代码一并提供出来
二.附录.本系列补充资源
2.1附加属性
很多样式中使用了附加属性来对基础控件扩展,ControlAttachProperty.cs所有代码:
/// <summary> /// 公共附加属性 /// </summary> public static class ControlAttachProperty { /************************************ Attach Property **************************************/ #region FocusBackground 获得焦点背景色, public static readonly DependencyProperty FocusBackgroundProperty = DependencyProperty.RegisterAttached( "FocusBackground", typeof(Brush), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static void SetFocusBackground(DependencyObject element, Brush value) { element.SetValue(FocusBackgroundProperty, value); } public static Brush GetFocusBackground(DependencyObject element) { return (Brush)element.GetValue(FocusBackgroundProperty); } #endregion #region FocusForeground 获得焦点前景色, public static readonly DependencyProperty FocusForegroundProperty = DependencyProperty.RegisterAttached( "FocusForeground", typeof(Brush), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static void SetFocusForeground(DependencyObject element, Brush value) { element.SetValue(FocusForegroundProperty, value); } public static Brush GetFocusForeground(DependencyObject element) { return (Brush)element.GetValue(FocusForegroundProperty); } #endregion #region MouseOverBackgroundProperty 鼠标悬浮背景色 public static readonly DependencyProperty MouseOverBackgroundProperty = DependencyProperty.RegisterAttached( "MouseOverBackground", typeof(Brush), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static void SetMouseOverBackground(DependencyObject element, Brush value) { element.SetValue(MouseOverBackgroundProperty, value); } public static Brush MouseOverBackground(DependencyObject element) { return (Brush)element.GetValue(FocusBackgroundProperty); } #endregion #region MouseOverForegroundProperty 鼠标悬浮前景色 public static readonly DependencyProperty MouseOverForegroundProperty = DependencyProperty.RegisterAttached( "MouseOverForeground", typeof(Brush), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static void SetMouseOverForeground(DependencyObject element, Brush value) { element.SetValue(MouseOverForegroundProperty, value); } public static Brush MouseOverForeground(DependencyObject element) { return (Brush)element.GetValue(FocusForegroundProperty); } #endregion #region FocusBorderBrush 焦点边框色,输入控件 public static readonly DependencyProperty FocusBorderBrushProperty = DependencyProperty.RegisterAttached( "FocusBorderBrush", typeof(Brush), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static void SetFocusBorderBrush(DependencyObject element, Brush value) { element.SetValue(FocusBorderBrushProperty, value); } public static Brush GetFocusBorderBrush(DependencyObject element) { return (Brush)element.GetValue(FocusBorderBrushProperty); } #endregion #region MouseOverBorderBrush 鼠标进入边框色,输入控件 public static readonly DependencyProperty MouseOverBorderBrushProperty = DependencyProperty.RegisterAttached("MouseOverBorderBrush", typeof(Brush), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits)); /// <summary> /// Sets the brush used to draw the mouse over brush. /// </summary> public static void SetMouseOverBorderBrush(DependencyObject obj, Brush value) { obj.SetValue(MouseOverBorderBrushProperty, value); } /// <summary> /// Gets the brush used to draw the mouse over brush. /// </summary> [AttachedPropertyBrowsableForType(typeof(TextBox))] [AttachedPropertyBrowsableForType(typeof(CheckBox))] [AttachedPropertyBrowsableForType(typeof(RadioButton))] [AttachedPropertyBrowsableForType(typeof(DatePicker))] [AttachedPropertyBrowsableForType(typeof(ComboBox))] [AttachedPropertyBrowsableForType(typeof(RichTextBox))] public static Brush GetMouseOverBorderBrush(DependencyObject obj) { return (Brush)obj.GetValue(MouseOverBorderBrushProperty); } #endregion #region AttachContentProperty 附加组件模板 /// <summary> /// 附加组件模板 /// </summary> public static readonly DependencyProperty AttachContentProperty = DependencyProperty.RegisterAttached( "AttachContent", typeof(ControlTemplate), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static ControlTemplate GetAttachContent(DependencyObject d) { return (ControlTemplate)d.GetValue(AttachContentProperty); } public static void SetAttachContent(DependencyObject obj, ControlTemplate value) { obj.SetValue(AttachContentProperty, value); } #endregion #region WatermarkProperty 水印 /// <summary> /// 水印 /// </summary> public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached( "Watermark", typeof(string), typeof(ControlAttachProperty), new FrameworkPropertyMetadata("")); public static string GetWatermark(DependencyObject d) { return (string)d.GetValue(WatermarkProperty); } public static void SetWatermark(DependencyObject obj, string value) { obj.SetValue(WatermarkProperty, value); } #endregion #region FIconProperty 字体图标 /// <summary> /// 字体图标 /// </summary> public static readonly DependencyProperty FIconProperty = DependencyProperty.RegisterAttached( "FIcon", typeof(string), typeof(ControlAttachProperty), new FrameworkPropertyMetadata("")); public static string GetFIcon(DependencyObject d) { return (string)d.GetValue(FIconProperty); } public static void SetFIcon(DependencyObject obj, string value) { obj.SetValue(FIconProperty, value); } #endregion #region FIconSizeProperty 字体图标大小 /// <summary> /// 字体图标 /// </summary> public static readonly DependencyProperty FIconSizeProperty = DependencyProperty.RegisterAttached( "FIconSize", typeof(double), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(12D)); public static double GetFIconSize(DependencyObject d) { return (double)d.GetValue(FIconSizeProperty); } public static void SetFIconSize(DependencyObject obj, double value) { obj.SetValue(FIconSizeProperty, value); } #endregion #region FIconMarginProperty 字体图标边距 /// <summary> /// 字体图标 /// </summary> public static readonly DependencyProperty FIconMarginProperty = DependencyProperty.RegisterAttached( "FIconMargin", typeof(Thickness), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static Thickness GetFIconMargin(DependencyObject d) { return (Thickness)d.GetValue(FIconMarginProperty); } public static void SetFIconMargin(DependencyObject obj, Thickness value) { obj.SetValue(FIconMarginProperty, value); } #endregion #region AllowsAnimationProperty 启用旋转动画 /// <summary> /// 启用旋转动画 /// </summary> public static readonly DependencyProperty AllowsAnimationProperty = DependencyProperty.RegisterAttached("AllowsAnimation" , typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false, AllowsAnimationChanged)); public static bool GetAllowsAnimation(DependencyObject d) { return (bool)d.GetValue(AllowsAnimationProperty); } public static void SetAllowsAnimation(DependencyObject obj, bool value) { obj.SetValue(AllowsAnimationProperty, value); } /// <summary> /// 旋转动画刻度 /// </summary> private static DoubleAnimation RotateAnimation = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(200))); /// <summary> /// 绑定动画事件 /// </summary> private static void AllowsAnimationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var uc = d as FrameworkElement; if (uc == null) return; if (uc.RenderTransformOrigin == new Point(0, 0)) { uc.RenderTransformOrigin = new Point(0.5, 0.5); RotateTransform trans = new RotateTransform(0); uc.RenderTransform = trans; } var value = (bool)e.NewValue; if (value) { RotateAnimation.To = 180; uc.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, RotateAnimation); } else { RotateAnimation.To = 0; uc.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, RotateAnimation); } } #endregion #region CornerRadiusProperty Border圆角 /// <summary> /// Border圆角 /// </summary> public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached( "CornerRadius", typeof(CornerRadius), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); public static CornerRadius GetCornerRadius(DependencyObject d) { return (CornerRadius)d.GetValue(CornerRadiusProperty); } public static void SetCornerRadius(DependencyObject obj, CornerRadius value) { obj.SetValue(CornerRadiusProperty, value); } #endregion #region LabelProperty TextBox的头部Label /// <summary> /// TextBox的头部Label /// </summary> public static readonly DependencyProperty LabelProperty = DependencyProperty.RegisterAttached( "Label", typeof(string), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); [AttachedPropertyBrowsableForType(typeof(TextBox))] public static string GetLabel(DependencyObject d) { return (string)d.GetValue(LabelProperty); } public static void SetLabel(DependencyObject obj, string value) { obj.SetValue(LabelProperty, value); } #endregion #region LabelTemplateProperty TextBox的头部Label模板 /// <summary> /// TextBox的头部Label模板 /// </summary> public static readonly DependencyProperty LabelTemplateProperty = DependencyProperty.RegisterAttached( "LabelTemplate", typeof(ControlTemplate), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null)); [AttachedPropertyBrowsableForType(typeof(TextBox))] public static ControlTemplate GetLabelTemplate(DependencyObject d) { return (ControlTemplate)d.GetValue(LabelTemplateProperty); } public static void SetLabelTemplate(DependencyObject obj, ControlTemplate value) { obj.SetValue(LabelTemplateProperty, value); } #endregion /************************************ RoutedUICommand Behavior enable **************************************/ #region IsClearTextButtonBehaviorEnabledProperty 清除输入框Text值按钮行为开关(设为ture时才会绑定事件) /// <summary> /// 清除输入框Text值按钮行为开关 /// </summary> public static readonly DependencyProperty IsClearTextButtonBehaviorEnabledProperty = DependencyProperty.RegisterAttached("IsClearTextButtonBehaviorEnabled" , typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false, IsClearTextButtonBehaviorEnabledChanged)); [AttachedPropertyBrowsableForType(typeof(TextBox))] public static bool GetIsClearTextButtonBehaviorEnabled(DependencyObject d) { return (bool)d.GetValue(IsClearTextButtonBehaviorEnabledProperty); } public static void SetIsClearTextButtonBehaviorEnabled(DependencyObject obj, bool value) { obj.SetValue(IsClearTextButtonBehaviorEnabledProperty, value); } /// <summary> /// 绑定清除Text操作的按钮事件 /// </summary> private static void IsClearTextButtonBehaviorEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var button = d as FButton; if (e.OldValue != e.NewValue && button != null) { button.CommandBindings.Add(ClearTextCommandBinding); } } #endregion #region IsOpenFileButtonBehaviorEnabledProperty 选择文件命令行为开关 /// <summary> /// 选择文件命令行为开关 /// </summary> public static readonly DependencyProperty IsOpenFileButtonBehaviorEnabledProperty = DependencyProperty.RegisterAttached("IsOpenFileButtonBehaviorEnabled" , typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false, IsOpenFileButtonBehaviorEnabledChanged)); [AttachedPropertyBrowsableForType(typeof(TextBox))] public static bool GetIsOpenFileButtonBehaviorEnabled(DependencyObject d) { return (bool)d.GetValue(IsOpenFileButtonBehaviorEnabledProperty); } public static void SetIsOpenFileButtonBehaviorEnabled(DependencyObject obj, bool value) { obj.SetValue(IsOpenFileButtonBehaviorEnabledProperty, value); } private static void IsOpenFileButtonBehaviorEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var button = d as FButton; if (e.OldValue != e.NewValue && button != null) { button.CommandBindings.Add(OpenFileCommandBinding); } } #endregion #region IsOpenFolderButtonBehaviorEnabledProperty 选择文件夹命令行为开关 /// <summary> /// 选择文件夹命令行为开关 /// </summary> public static readonly DependencyProperty IsOpenFolderButtonBehaviorEnabledProperty = DependencyProperty.RegisterAttached("IsOpenFolderButtonBehaviorEnabled" , typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false, IsOpenFolderButtonBehaviorEnabledChanged)); [AttachedPropertyBrowsableForType(typeof(TextBox))] public static bool GetIsOpenFolderButtonBehaviorEnabled(DependencyObject d) { return (bool)d.GetValue(IsOpenFolderButtonBehaviorEnabledProperty); } public static void SetIsOpenFolderButtonBehaviorEnabled(DependencyObject obj, bool value) { obj.SetValue(IsOpenFolderButtonBehaviorEnabledProperty, value); } private static void IsOpenFolderButtonBehaviorEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var button = d as FButton; if (e.OldValue != e.NewValue && button != null) { button.CommandBindings.Add(OpenFolderCommandBinding); } } #endregion #region IsSaveFileButtonBehaviorEnabledProperty 选择文件保存路径及名称 /// <summary> /// 选择文件保存路径及名称 /// </summary> public static readonly DependencyProperty IsSaveFileButtonBehaviorEnabledProperty = DependencyProperty.RegisterAttached("IsSaveFileButtonBehaviorEnabled" , typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false, IsSaveFileButtonBehaviorEnabledChanged)); [AttachedPropertyBrowsableForType(typeof(TextBox))] public static bool GetIsSaveFileButtonBehaviorEnabled(DependencyObject d) { return (bool)d.GetValue(IsSaveFileButtonBehaviorEnabledProperty); } public static void SetIsSaveFileButtonBehaviorEnabled(DependencyObject obj, bool value) { obj.SetValue(IsSaveFileButtonBehaviorEnabledProperty, value); } private static void IsSaveFileButtonBehaviorEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var button = d as FButton; if (e.OldValue != e.NewValue && button != null) { button.CommandBindings.Add(SaveFileCommandBinding); } } #endregion /************************************ RoutedUICommand **************************************/ #region ClearTextCommand 清除输入框Text事件命令 /// <summary> /// 清除输入框Text事件命令,需要使用IsClearTextButtonBehaviorEnabledChanged绑定命令 /// </summary> public static RoutedUICommand ClearTextCommand { get; private set; } /// <summary> /// ClearTextCommand绑定事件 /// </summary> private static readonly CommandBinding ClearTextCommandBinding; /// <summary> /// 清除输入框文本值 /// </summary> private static void ClearButtonClick(object sender, ExecutedRoutedEventArgs e) { var tbox = e.Parameter as FrameworkElement; if (tbox == null) return; if (tbox is TextBox) { ((TextBox)tbox).Clear(); } if (tbox is PasswordBox) { ((PasswordBox)tbox).Clear(); } if (tbox is ComboBox) { var cb = tbox as ComboBox; cb.SelectedItem = null; cb.Text = string.Empty; } if (tbox is MultiComboBox) { var cb = tbox as MultiComboBox; cb.SelectedItem = null; cb.UnselectAll(); cb.Text = string.Empty; } if (tbox is DatePicker) { var dp = tbox as DatePicker; dp.SelectedDate = null; dp.Text = string.Empty; } tbox.Focus(); } #endregion #region OpenFileCommand 选择文件命令 /// <summary> /// 选择文件命令,需要使用IsClearTextButtonBehaviorEnabledChanged绑定命令 /// </summary> public static RoutedUICommand OpenFileCommand { get; private set; } /// <summary> /// OpenFileCommand绑定事件 /// </summary> private static readonly CommandBinding OpenFileCommandBinding; /// <summary> /// 执行OpenFileCommand /// </summary> private static void OpenFileButtonClick(object sender, ExecutedRoutedEventArgs e) { var tbox = e.Parameter as FrameworkElement; var txt = tbox as TextBox; string filter = txt.Tag == null ? "所有文件(*.*)|*.*" : txt.Tag.ToString(); if (filter.Contains(".bin")) { filter += "|所有文件(*.*)|*.*"; } if (txt == null) return; OpenFileDialog fd = new OpenFileDialog(); fd.Title = "请选择文件"; //“图像文件(*.bmp, *.jpg)|*.bmp;*.jpg|所有文件(*.*)|*.*” fd.Filter = filter; fd.FileName = txt.Text.Trim(); if (fd.ShowDialog() == true) { txt.Text = fd.FileName; } tbox.Focus(); } #endregion #region OpenFolderCommand 选择文件夹命令 /// <summary> /// 选择文件夹命令 /// </summary> public static RoutedUICommand OpenFolderCommand { get; private set; } /// <summary> /// OpenFolderCommand绑定事件 /// </summary> private static readonly CommandBinding OpenFolderCommandBinding; /// <summary> /// 执行OpenFolderCommand /// </summary> private static void OpenFolderButtonClick(object sender, ExecutedRoutedEventArgs e) { var tbox = e.Parameter as FrameworkElement; var txt = tbox as TextBox; if (txt == null) return; FolderBrowserDialog fd = new FolderBrowserDialog(); fd.Description = "请选择文件路径"; fd.SelectedPath = txt.Text.Trim(); if (fd.ShowDialog() == DialogResult.OK) { txt.Text = fd.SelectedPath; } tbox.Focus(); } #endregion #region SaveFileCommand 选择文件保存路径及名称 /// <summary> /// 选择文件保存路径及名称 /// </summary> public static RoutedUICommand SaveFileCommand { get; private set; } /// <summary> /// SaveFileCommand绑定事件 /// </summary> private static readonly CommandBinding SaveFileCommandBinding; /// <summary> /// 执行OpenFileCommand /// </summary> private static void SaveFileButtonClick(object sender, ExecutedRoutedEventArgs e) { var tbox = e.Parameter as FrameworkElement; var txt = tbox as TextBox; if (txt == null) return; SaveFileDialog fd = new SaveFileDialog(); fd.Title = "文件保存路径"; fd.Filter = "所有文件(*.*)|*.*"; fd.FileName = txt.Text.Trim(); if (fd.ShowDialog() == DialogResult.OK) { txt.Text = fd.FileName; } tbox.Focus(); } #endregion /// <summary> /// 静态构造函数 /// </summary> static ControlAttachProperty() { //ClearTextCommand ClearTextCommand = new RoutedUICommand(); ClearTextCommandBinding = new CommandBinding(ClearTextCommand); ClearTextCommandBinding.Executed += ClearButtonClick; //OpenFileCommand OpenFileCommand = new RoutedUICommand(); OpenFileCommandBinding = new CommandBinding(OpenFileCommand); OpenFileCommandBinding.Executed += OpenFileButtonClick; //OpenFolderCommand OpenFolderCommand = new RoutedUICommand(); OpenFolderCommandBinding = new CommandBinding(OpenFolderCommand); OpenFolderCommandBinding.Executed += OpenFolderButtonClick; SaveFileCommand = new RoutedUICommand(); SaveFileCommandBinding = new CommandBinding(SaveFileCommand); SaveFileCommandBinding.Executed += SaveFileButtonClick; } }
其中有一个比较好玩的附加属性就是AllowsAnimationProperty,实现旋转动画的支持,类型为bool,可以有很多种使用方式,如绑定到普通控件的IsMouseOver上,当鼠标悬浮就旋转180度,移开又转回去,效果(gif录制的问题,看上去没有那么流程):
也可以绑定到CheckBox、RadioButton、ToggleButton的IsChecked属性上。
<TextBlock Text="" Style="{StaticResource FIcon}" Margin="3" FontSize="40" core:ControlAttachProperty.AllowsAnimation="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}"></TextBlock> <core:FImage Margin="3" Width="30" Height="30" Source="Images/qq.png"
core:ControlAttachProperty.AllowsAnimation="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}"></core:FImage>
2.2扩展方法
静态扩展类ControlExtession.cs代码:
public static class ControlExtession { #region BindCommand /// <summary> /// 绑定命令和命令事件到宿主UI /// </summary> public static void BindCommand(this UIElement @ui, ICommand com, Action<object, ExecutedRoutedEventArgs> call) { var bind = new CommandBinding(com); bind.Executed += new ExecutedRoutedEventHandler(call); @ui.CommandBindings.Add(bind); } /// <summary> /// 绑定RelayCommand命令到宿主UI /// </summary> public static void BindCommand(this UIElement @ui, RelayCommand<object> com) { var bind = new CommandBinding(com); bind.Executed += delegate(object sender, ExecutedRoutedEventArgs e) { com.ExecuteCommand(e.Parameter); }; @ui.CommandBindings.Add(bind); } #endregion #region TreeView操作扩展方法 //code:http://www.codeproject.com/Articles/36193/WPF-TreeView-tools /// <summary> /// Returns the TreeViewItem of a data bound object. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> /// <returns>The TreeViewItem of the data bound object or null.</returns> public static TreeViewItem GetItemFromObject(this TreeView treeView, object obj) { try { DependencyObject dObject = GetContainerFormObject(treeView, obj); TreeViewItem tvi = dObject as TreeViewItem; while (tvi == null) { dObject = VisualTreeHelper.GetParent(dObject); tvi = dObject as TreeViewItem; } return tvi; } catch { } return null; } private static DependencyObject GetContainerFormObject(ItemsControl item, object obj) { if (item == null) return null; DependencyObject dObject = null; dObject = item.ItemContainerGenerator.ContainerFromItem(obj); if (dObject != null) return dObject; var query = from childItem in item.Items.Cast<object>() let childControl = item.ItemContainerGenerator.ContainerFromItem(childItem) as ItemsControl select GetContainerFormObject(childControl, obj); return query.FirstOrDefault(i => i != null); } /// <summary> /// Selects a data bound object of a TreeView. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> public static void SelectObject(this TreeView treeView, object obj) { treeView.SelectObject(obj, true); } /// <summary> /// Selects or deselects a data bound object of a TreeView. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> /// <param name="selected">select or deselect</param> public static void SelectObject(this TreeView treeView, object obj, bool selected) { var tvi = treeView.GetItemFromObject(obj); if (tvi != null) { tvi.IsSelected = selected; } } /// <summary> /// Returns if a data bound object of a TreeView is selected. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> /// <returns>Returns true if the object is selected, and false if it is not selected or obj is not in the tree.</returns> public static bool IsObjectSelected(this TreeView treeView, object obj) { var tvi = treeView.GetItemFromObject(obj); if (tvi != null) { return tvi.IsSelected; } return false; } /// <summary> /// Returns if a data bound object of a TreeView is focused. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> /// <returns>Returns true if the object is focused, and false if it is not focused or obj is not in the tree.</returns> public static bool IsObjectFocused(this TreeView treeView, object obj) { var tvi = treeView.GetItemFromObject(obj); if (tvi != null) { return tvi.IsFocused; } return false; } /// <summary> /// Expands a data bound object of a TreeView. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> public static void ExpandObject(this TreeView treeView, object obj) { treeView.ExpandObject(obj, true); } /// <summary> /// Expands or collapses a data bound object of a TreeView. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> /// <param name="expanded">expand or collapse</param> public static void ExpandObject(this TreeView treeView, object obj, bool expanded) { var tvi = treeView.GetItemFromObject(obj); if (tvi != null) { tvi.IsExpanded = expanded; if (expanded) { // update layout, so that following calls to f.e. SelectObject on child nodes will // find theire TreeViewNodes treeView.UpdateLayout(); } } } /// <summary> /// Returns if a douta bound object of a TreeView is expanded. /// </summary> /// <param name="treeView">TreeView</param> /// <param name="obj">Data bound object</param> /// <returns>Returns true if the object is expanded, and false if it is collapsed or obj is not in the tree.</returns> public static bool IsObjectExpanded(this TreeView treeView, object obj) { var tvi = treeView.GetItemFromObject(obj); if (tvi != null) { return tvi.IsExpanded; } return false; } /// <summary> /// Retuns the parent TreeViewItem. /// </summary> /// <param name="item">TreeViewItem</param> /// <returns>Parent TreeViewItem</returns> public static TreeViewItem GetParentItem(this TreeViewItem item) { var dObject = VisualTreeHelper.GetParent(item); TreeViewItem tvi = dObject as TreeViewItem; while (tvi == null) { dObject = VisualTreeHelper.GetParent(dObject); tvi = dObject as TreeViewItem; } return tvi; } #endregion }
2.3配色资源Colors.xaml
本系列前面文章中,基本所有样式中都没有直接使用具体色彩,而是通过资源的方式配置的,这些配色资源都在Colors.xaml中。这样的设计理论上可以实现换肤,在不同客户端中也很容易定制自己需要的风格色彩搭配。 Colors.xaml代码:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!--Window窗体--> <SolidColorBrush x:Key="WindowBackground" Color="#093B5D"></SolidColorBrush> <SolidColorBrush x:Key="WindowInnerBackground" Color="Transparent"></SolidColorBrush> <!--<ImageBrush x:Key="WindowInnerBackground" Stretch="Fill" ImageSource="pack://application:,,,/XLY.Framework.WPFTest;component/Images/back/b2.jpg" Opacity="1" Viewport="0,0,1,1" ViewportUnits="Absolute" TileMode="Tile" AlignmentX="Left" AlignmentY="Top"/>--> <SolidColorBrush x:Key="WindowBorderBrush" Color="#920892"></SolidColorBrush> <DropShadowEffect x:Key="WindowDropShadow" Color="#F472F4" BlurRadius="8" ShadowDepth="0" Direction="0" Opacity="0.7" /> <SolidColorBrush x:Key="CaptionForeground" Color="White"></SolidColorBrush> <!--<LinearGradientBrush x:Key="CaptionBackground" StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="#571457" Offset="0"/> <GradientStop Color="#6A196A" Offset="1"/> </LinearGradientBrush>--> <ImageBrush x:Key="CaptionBackground" ImageSource="pack://application:,,,/XLY.Framework.WPFTest;component/Images/back/b2.jpg" Opacity="1" Viewport="0,0,202,143" ViewportUnits="Absolute" TileMode="Tile" AlignmentX="Left" AlignmentY="Top"/> <!--MessageBoxX--> <SolidColorBrush x:Key="InfoForeground" Color="White"></SolidColorBrush> <SolidColorBrush x:Key="QuestionForeground" Color="#74B80C"></SolidColorBrush> <SolidColorBrush x:Key="WarningForeground" Color="DarkOrange"></SolidColorBrush> <SolidColorBrush x:Key="ErrorForeground" Color="#E74E4E"></SolidColorBrush> <!--WaitingBox--> <SolidColorBrush x:Key="WaitingBoxBackground" Color="#921692"></SolidColorBrush> <!--边框:Menu--> <DropShadowEffect x:Key="DefaultDropShadow" Color="Black" BlurRadius="5" ShadowDepth="2" Direction="315" Opacity="0.6" /> <!--输入组件--> <SolidColorBrush x:Key="TextForeground" Color="White"></SolidColorBrush> <SolidColorBrush x:Key="TextBackground" Color="#0D234B"></SolidColorBrush> <SolidColorBrush x:Key="TextSelectionBrush" Color="#8F8787"></SolidColorBrush> <!--TextBox默认Label颜色--> <SolidColorBrush x:Key="TextLabelBackground" Color="#508AB6"></SolidColorBrush> <!--输入框--> <SolidColorBrush x:Key="ControlBorderBrush" Color="#999C9F"></SolidColorBrush> <SolidColorBrush x:Key="MouseOverBorderBrush" Color="#F6D1D1"></SolidColorBrush> <SolidColorBrush x:Key="FocusBackground" Color="#365080"></SolidColorBrush> <SolidColorBrush x:Key="FocusBorderBrush" Color="#EBCECE"></SolidColorBrush> <!--ScrollBar--> <SolidColorBrush x:Key="ScrollBarForeround" Color="#877F7F"></SolidColorBrush> <SolidColorBrush x:Key="ScrollBarBackground" Color="#3E3E42"></SolidColorBrush> <!--ItemsControl:DataGrid,Tree--> <sys:Double x:Key="HeaderFontSize">14</sys:Double> <SolidColorBrush x:Key="HeaderBorderBrush" Color="#A6FFA500"></SolidColorBrush> <SolidColorBrush x:Key="HeaderBackground" Color="#0A48D3"></SolidColorBrush> <SolidColorBrush x:Key="ItemsContentBackground" Color="#1389D7"></SolidColorBrush> <SolidColorBrush x:Key="ItemsAlternationContentBackground" Color="#128EE0"></SolidColorBrush> <SolidColorBrush x:Key="GridLinesBrush" Color="#A6D0C2A7"></SolidColorBrush> <SolidColorBrush x:Key="ItemSelectedForeground" Color="White"></SolidColorBrush> <SolidColorBrush x:Key="ItemSelectedBackground" Color="#A145F8"></SolidColorBrush> <SolidColorBrush x:Key="ItemMouseOverBackground" Color="#BA7DF4"></SolidColorBrush> <SolidColorBrush x:Key="ItemMouseOverForeground" Color="White"></SolidColorBrush> <!--高亮:日历Today--> <SolidColorBrush x:Key="ItemHighlighteBackground" Color="Blue"></SolidColorBrush> <SolidColorBrush x:Key="ItemHighlighteForeground" Color="White"></SolidColorBrush> <!--普通无背景按钮--> <SolidColorBrush x:Key="CheckedForeground" Color="#F7B63E"></SolidColorBrush> <SolidColorBrush x:Key="MouseOverForeground" Color="Orange"></SolidColorBrush> <SolidColorBrush x:Key="PressedForeground" Color="DarkOrange"></SolidColorBrush> <SolidColorBrush x:Key="LinkForeground" Color="#0816BB"></SolidColorBrush> <!--Popup,ComboBox--> <SolidColorBrush x:Key="PopupBackground" Color="#066EB3"></SolidColorBrush> <!--Button--> <SolidColorBrush x:Key="ButtonBackground" Color="#1D4A9A"></SolidColorBrush> <SolidColorBrush x:Key="ButtonForeground" Color="White"></SolidColorBrush> <SolidColorBrush x:Key="ButtonMouseOverBackground" Color="Orange"></SolidColorBrush> <SolidColorBrush x:Key="ButtonMouseOverForeground" Color="White"></SolidColorBrush> <SolidColorBrush x:Key="ButtonPressedBackground" Color="DarkOrange"></SolidColorBrush> <SolidColorBrush x:Key="ButtonPressedForeground" Color="White"></SolidColorBrush> <!--Menu--> <SolidColorBrush x:Key="MenuForeground" Color="#920892"></SolidColorBrush> <SolidColorBrush x:Key="MenuBackground" Color="#DDD1D1"></SolidColorBrush> <SolidColorBrush x:Key="MenuBorderBrush" Color="DarkBlue"></SolidColorBrush> <SolidColorBrush x:Key="MenuMouseOverBackground" Color="#0D3CD2"></SolidColorBrush> <SolidColorBrush x:Key="MenuMouseOverForeground" Color="White"></SolidColorBrush> <SolidColorBrush x:Key="MenuPressedBackground" Color="#082CA0"></SolidColorBrush> <SolidColorBrush x:Key="MenuPressedForeground" Color="White"></SolidColorBrush> <!--State brush--> <SolidColorBrush x:Key="SuccessfulfaiBrush" Color="#16B32A"></SolidColorBrush> <SolidColorBrush x:Key="FailedBrush" Color="#B92222"></SolidColorBrush> <FontFamily x:Key="FontFamily" >Microsoft YaHei</FontFamily> <sys:Double x:Key="FontSize">13</sys:Double> <sys:Double x:Key="DisableOpacity">0.5</sys:Double> <sys:Double x:Key="ReadonlyOpacity">0.88</sys:Double> <sys:Double x:Key="WatermarkOpacity">0.4</sys:Double> <sys:String x:Key="DateFormat">yyyy年MM月dd日</sys:String> <sys:String x:Key="DateTimeFormat">yyyy-MM-dd HH:mm:ss</sys:String> </ResourceDictionary>
2.4转换器
BackgroundToForegroundConverter.cs代码:
/// <summary> /// 根据背景色获取前景色。当然也可反着用 /// </summary> public class BackgroundToForegroundConverter : IValueConverter { private Color IdealTextColor(Color bg) { const int nThreshold = 105; var bgDelta = System.Convert.ToInt32((bg.R * 0.299) + (bg.G * 0.587) + (bg.B * 0.114)); var foreColor = (255 - bgDelta < nThreshold) ? Colors.Black : Colors.White; return foreColor; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is SolidColorBrush) { var idealForegroundColor = this.IdealTextColor(((SolidColorBrush)value).Color); var foreGroundBrush = new SolidColorBrush(idealForegroundColor); foreGroundBrush.Freeze(); return foreGroundBrush; } return Brushes.White; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return DependencyProperty.UnsetValue; } }
PercentToAngleConverter.cs代码:
/// <summary> /// 百分比转换为角度值 /// </summary> public class PercentToAngleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var percent = value.ToSafeString().ToDouble(); if (percent >= 1) return 360.0D; return percent * 360; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
ThicknessToDoubleConverter.cs代码:
/// <summary> /// 获取Thickness固定值double /// </summary> public class ThicknessToDoubleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var thickness = (Thickness)value; return thickness.Left; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return DependencyProperty.UnsetValue; } }
TreeViewMarginConverter.cs代码:
/// <summary> /// 计算树节点的左缩进位置 /// </summary> public class TreeViewMarginConverter : IValueConverter { public double Length { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var item = value as TreeViewItem; if (item == null) return new Thickness(0); int dep = this.GetDepth(item); return new Thickness(Length * dep, 0, 0, 0); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return DependencyProperty.UnsetValue; } public int GetDepth(TreeViewItem item) { TreeViewItem parent; while ((parent = GetParent(item)) != null) { return GetDepth(parent) + 1; } return 0; } private TreeViewItem GetParent(TreeViewItem item) { var parent = item != null ? VisualTreeHelper.GetParent(item) : null; while (parent != null && !(parent is TreeViewItem || parent is TreeView)) { parent = VisualTreeHelper.GetParent(parent); } return parent as TreeViewItem; } }
TrueToFalseConverter.cs代码:
/// <summary> /// 这是一个颠倒黑白的世界 /// </summary> public sealed class TrueToFalseConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var v = (bool)value; return !v; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
为了使用简单,对常用的转换器定义了静态变量的引用:
/// <summary> /// 常用转换器的静态引用 /// 使用实例:Converter={x:Static local:XConverter.TrueToFalseConverter} /// </summary> public sealed class XConverter { public static BooleanToVisibilityConverter BooleanToVisibilityConverter { get { return Singleton<BooleanToVisibilityConverter>.GetInstance(); } } public static TrueToFalseConverter TrueToFalseConverter { get { return Singleton<TrueToFalseConverter>.GetInstance(); } } public static ThicknessToDoubleConverter ThicknessToDoubleConverter { get { return Singleton<ThicknessToDoubleConverter>.GetInstance(); } } public static BackgroundToForegroundConverter BackgroundToForegroundConverter { get { return Singleton<BackgroundToForegroundConverter>.GetInstance(); } } public static TreeViewMarginConverter TreeViewMarginConverter { get { return Singleton<TreeViewMarginConverter>.GetInstance(); } } public static PercentToAngleConverter PercentToAngleConverter { get { return Singleton<PercentToAngleConverter>.GetInstance(); } } }
然后使用时就不用在xaml中声明资源了,通过静态引用的方式使用,就是这样的:
2.6其他样式
Share.xaml:
<!--下拉按钮样式:ToggleButton样式 ['tɑɡl] 开关,触发器;拴扣;[船] 套索钉--> <!--图标大小:local:ControlAttachProperty.FIconSize--> <!--图标边距:local:ControlAttachProperty.FIconMargin--> <!--图标:local:ControlAttachProperty.FIcon--> <Style TargetType="{x:Type ToggleButton}" x:Key="ComboToggleButton"> <Setter Property="Foreground" Value="{StaticResource TextForeground}" /> <Setter Property="local:ControlAttachProperty.FIconSize" Value="18"/> <Setter Property="local:ControlAttachProperty.FIconMargin" Value="0,1,3,1"/> <Setter Property="local:ControlAttachProperty.FIcon" Value=""/> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Grid x:Name="Grid"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Border Background="{TemplateBinding Background}" x:Name="Bg" Grid.ColumnSpan="2" Margin="0,1,1,1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Opacity="0.3"/> <TextBlock Grid.Column="1" x:Name="FIcon" FontSize="{Binding Path=(local:ControlAttachProperty.FIconSize),RelativeSource={RelativeSource TemplatedParent}}" Text="{TemplateBinding local:ControlAttachProperty.FIcon}" local:ControlAttachProperty.AllowsAnimation="{TemplateBinding IsChecked}" Foreground="{TemplateBinding Foreground}" Style="{StaticResource FIcon}" Margin="{TemplateBinding local:ControlAttachProperty.FIconMargin}"/> </Grid> <!--z触发器--> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Foreground" Value="{StaticResource MouseOverForeground}" /> <Setter Property="Opacity" TargetName="Bg" Value="0.55" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter Property="Foreground" Value="{StaticResource PressedForeground}" /> <Setter Property="Opacity" TargetName="Bg" Value="0.6" /> </Trigger> <Trigger Property="IsChecked" Value="True"> <Setter Property="Foreground" Value="{StaticResource PressedForeground}" /> <Setter Property="Opacity" TargetName="Bg" Value="0.6" /> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="Grid"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <!--编辑状态文本框样式--> <Style TargetType="{x:Type TextBox}" x:Key="EditableTextBoxStyle"> <Setter Property="Margin" Value="1"/> <Setter Property="Padding" Value="0"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="Background" Value="{x:Null}"/> <Setter Property="MaxLength" Value="2048"/> <Setter Property="Foreground" Value="{StaticResource TextForeground}"/> <Setter Property="ContextMenu" Value="{DynamicResource TextBoxContextMenu}" /> <Setter Property="SelectionBrush" Value="{StaticResource TextSelectionBrush}" /> <Setter Property="FontSize" Value="{StaticResource FontSize}"></Setter> <Setter Property="FontFamily" Value="{StaticResource FontFamily}"></Setter> <Setter Property="Focusable" Value="True"/> <Setter Property="CaretBrush" Value="{StaticResource TextForeground}" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="SnapsToDevicePixels" Value="True"></Setter> <Style.Triggers> <Trigger Property="IsReadOnly" Value="True"> <Setter Property="Opacity" Value="{StaticResource ReadonlyOpacity}"></Setter> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Opacity" Value="{StaticResource DisableOpacity}"></Setter> </Trigger> </Style.Triggers> </Style>
Global.xaml
<!--TextBlock--> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Foreground" Value="{StaticResource TextForeground}"/> <Setter Property="FontFamily" Value="{StaticResource FontFamily}"/> <Setter Property="FontSize" Value="{StaticResource FontSize}"/> </Style> <!--ToolTip--> <Style TargetType="{x:Type ToolTip}"> <Setter Property="Foreground" Value="{StaticResource TextForeground}"/> <Setter Property="FontFamily" Value="{StaticResource FontFamily}"/> <Setter Property="FontSize" Value="{StaticResource FontSize}"/> <Setter Property="Background" Value="{StaticResource HeaderBackground}"/> <Setter Property="BorderBrush" Value="{StaticResource FocusBorderBrush}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToolTip}"> <Border CornerRadius="2" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}"> <ContentPresenter Margin="8,5,8,5"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
TablControl 的样式,TablControl.xaml
<Style x:Key="FIconTabItemStyle" TargetType="{x:Type TabItem}"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> <Setter Property="Background" Value="{StaticResource ButtonBackground}"/> <Setter Property="Foreground" Value="{StaticResource TextForeground}" /> <Setter Property="local:ControlAttachProperty.FIcon" Value=""/> <Setter Property="local:ControlAttachProperty.FIconSize" Value="26"/> <Setter Property="local:ControlAttachProperty.CornerRadius" Value="0"/> <Setter Property="local:ControlAttachProperty.FIconMargin" Value="0,0,2,0"/> <Setter Property="local:ControlAttachProperty.FocusBackground" Value="{StaticResource ButtonPressedBackground}"/> <Setter Property="local:ControlAttachProperty.FocusForeground" Value="{StaticResource ButtonMouseOverForeground}"/> <Setter Property="local:ControlAttachProperty.MouseOverBackground" Value="{StaticResource ButtonMouseOverBackground}"/> <Setter Property="local:ControlAttachProperty.MouseOverForeground" Value="{StaticResource ButtonPressedForeground}"/> <Setter Property="MinHeight" Value="20"/> <Setter Property="MinWidth" Value="20"/> <Setter Property="Margin" Value="0"/> <Setter Property="Padding" Value="3"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabItem}"> <Border x:Name="border" Margin="{TemplateBinding Margin}" SnapsToDevicePixels="True" ToolTip="{TemplateBinding ToolTip}" CornerRadius="{TemplateBinding local:ControlAttachProperty.CornerRadius}" Background="{TemplateBinding Background}"> <StackPanel VerticalAlignment="Center" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Orientation="Horizontal"> <TextBlock Style="{StaticResource FIcon}" Text="{TemplateBinding local:ControlAttachProperty.FIcon}" Margin="{TemplateBinding local:ControlAttachProperty.FIconMargin}" FontSize="{TemplateBinding local:ControlAttachProperty.FIconSize}" Foreground="{TemplateBinding Foreground}"/> <TextBlock x:Name="txtheader" VerticalAlignment="Center" Text="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}"/> </StackPanel> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="Background" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBackground),RelativeSource={RelativeSource Self}}"/> <Setter Property="Foreground" Value="{Binding Path=(local:ControlAttachProperty.MouseOverForeground),RelativeSource={RelativeSource Self}}"/> </Trigger> <Trigger Property="IsSelected" Value="true"> <Setter Property="Background" Value="{Binding Path=(local:ControlAttachProperty.FocusBackground),RelativeSource={RelativeSource Self}}"/> <Setter Property="Foreground" Value="{Binding Path=(local:ControlAttachProperty.FocusForeground),RelativeSource={RelativeSource Self}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="LeftTabControl" TargetType="{x:Type TabControl}"> <Setter Property="Padding" Value="0"/> <Setter Property="Background" Value="Transparent" /> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" /> <Setter Property="ItemContainerStyle" Value="{DynamicResource FIconTabItemStyle}"/> <Setter Property="TabStripPlacement" Value="Left"></Setter> <Setter Property="local:ControlAttachProperty.FocusBackground" Value="{StaticResource ButtonPressedBackground}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabControl}"> <Grid x:Name="PART_Root" Margin="{TemplateBinding Padding}" > <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Border BorderBrush="{TemplateBinding local:ControlAttachProperty.FocusBackground}" BorderThickness="0,0,2,0" > <StackPanel x:Name="HeaderPanel" Margin="0,5,0,5" Orientation="Vertical" IsItemsHost="True" ></StackPanel> </Border> <Border x:Name="ContentPanel" Grid.Column="1" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local" Width="Auto"> <ContentPresenter ContentSource="SelectedContent" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Width="Auto" /> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="TopTabControl" TargetType="{x:Type TabControl}"> <Setter Property="Padding" Value="0"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Background" Value="Transparent" /> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="ItemContainerStyle" Value="{StaticResource FIconTabItemStyle}"/> <Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" /> <Setter Property="TabStripPlacement" Value="Top"></Setter> <Setter Property="local:ControlAttachProperty.FocusBackground" Value="{StaticResource ButtonPressedBackground}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabControl}"> <Grid x:Name="PART_Root" Margin="{TemplateBinding Padding}" > <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Border BorderBrush="{TemplateBinding local:ControlAttachProperty.FocusBackground}" BorderThickness="0,0,0,2" > <StackPanel x:Name="HeaderPanel" Margin="5,0,5,0" Orientation="Horizontal" IsItemsHost="True" ></StackPanel> </Border> <Border x:Name="ContentPanel" Grid.Row="1" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local" Width="Auto"> <ContentPresenter ContentSource="SelectedContent" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Width="Auto"/> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
ToggleButton的样式资源
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:XLY.Framework.Controls" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="{x:Type ToggleButton}" x:Key="DefaultToggleButton"> <Setter Property="Foreground" Value="{StaticResource TextForeground}" /> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Grid x:Name="Grid" Margin="{TemplateBinding Padding}"> <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> <!--z触发器--> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Foreground" Value="{StaticResource MouseOverForeground}" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter Property="Foreground" Value="{StaticResource PressedForeground}" /> </Trigger> <Trigger Property="IsChecked" Value="True"> <Setter Property="Foreground" Value="{StaticResource PressedForeground}" /> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="Grid"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type ToggleButton}" x:Key="FIconToggleButton"> <Setter Property="Foreground" Value="{StaticResource TextForeground}" /> <Setter Property="local:ControlAttachProperty.FIconSize" Value="20"/> <Setter Property="local:ControlAttachProperty.FIconMargin" Value="1"/> <Setter Property="local:ControlAttachProperty.FIcon" Value=""/> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="Padding" Value="0" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Grid x:Name="Grid" Margin="{TemplateBinding Padding}"> <TextBlock x:Name="FIcon" FontSize="{Binding Path=(local:ControlAttachProperty.FIconSize),RelativeSource={RelativeSource TemplatedParent}}" Text="{TemplateBinding local:ControlAttachProperty.FIcon}" Foreground="{TemplateBinding Foreground}" Style="{StaticResource FIcon}" Margin="{TemplateBinding local:ControlAttachProperty.FIconMargin}"/> </Grid> <!--z触发器--> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Foreground" Value="{StaticResource MouseOverForeground}" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter Property="Foreground" Value="{StaticResource PressedForeground}" /> </Trigger> <Trigger Property="IsChecked" Value="True"> <Setter Property="Foreground" Value="{StaticResource PressedForeground}" /> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="Grid"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
版权所有,文章来源:http://www.cnblogs.com/anding
个人能力有限,本文内容仅供学习、探讨,欢迎指正、交流。