using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace Muchinfo.WPF.Controls { /// /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。 /// /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:Muchinfo.MTPClient.Account.Views" /// /// /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:Muchinfo.MTPClient.Account.Views;assembly=Muchinfo.MTPClient.Account.Views" /// /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用, /// 并重新生成以避免编译错误: /// /// 在解决方案资源管理器中右击目标项目,然后依次单击 /// “添加引用”->“项目”->[浏览查找并选择此项目] /// /// /// 步骤 2) /// 继续操作并在 XAML 文件中使用控件。 /// /// /// /// // [TemplatePart(Name = "XscrollViewer", Type = typeof(ScrollViewer))] [TemplatePart(Name = "PART_HorizontalScrollBar", Type = typeof(ScrollBar))] [TemplatePart(Name = "PART_SelectedContentHost", Type = typeof(ContentPresenter))] [TemplatePart(Name = "Part_TabViewer", Type = typeof(ScrollViewer))] public class OrderTabControl : TabControl { static OrderTabControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(OrderTabControl), new FrameworkPropertyMetadata(typeof(OrderTabControl))); } public OrderTabControl() { this.LayoutUpdated += OrderTabControl_LayoutUpdated; } void OrderTabControl_LayoutUpdated(object sender, EventArgs e) { // SetScrollBar(); } private ScrollViewer scrollViewer = null; private ScrollBar scrollBar = null; private ContentPresenter presenter = null; private bool _isSelectedChange = false; public override void OnApplyTemplate() { base.OnApplyTemplate(); // scrollViewer = this.GetTemplateChild("XscrollViewer") as ScrollViewer; scrollBar = this.GetTemplateChild("PART_HorizontalScrollBar") as ScrollBar; scrollViewer = this.GetTemplateChild("Part_TabViewer") as ScrollViewer; if (scrollBar != null) { scrollBar.ValueChanged+=scrollBar_ValueChanged; } } /// /// 横向滚动条的值 /// public double HSValue { get { return (double)GetValue(HSValueProperty); } set { SetValue(HSValueProperty, value); } } // Using a DependencyProperty as the backing store for HSValue. This enables animation, styling, binding, etc... public static readonly DependencyProperty HSValueProperty = DependencyProperty.Register("HSValue", typeof(double), typeof(OrderTabControl), new PropertyMetadata(0d,HSValueChangecalback)); /// /// 横向滚动条 /// public double ViewportWidth { get { return (double)GetValue(ViewportWidthProperty); } set { SetValue(ViewportWidthProperty, value); } } // Using a DependencyProperty as the backing store for ViewportWidth. This enables animation, styling, binding, etc... public static readonly DependencyProperty ViewportWidthProperty = DependencyProperty.Register("ViewportWidth", typeof(double), typeof(OrderTabControl), new PropertyMetadata(0d)); public double ScrollableWidth { get { return (double)GetValue(ScrollableWidthProperty); } set { SetValue(ScrollableWidthProperty, value); } } // Using a DependencyProperty as the backing store for ScrollableWidth. This enables animation, styling, binding, etc... public static readonly DependencyProperty ScrollableWidthProperty = DependencyProperty.Register("ScrollableWidth", typeof(double), typeof(OrderTabControl), new PropertyMetadata(0d)); private static void HSValueChangecalback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var oTabControl = d as OrderTabControl; if (oTabControl != null && oTabControl.scrollViewer!=null) { oTabControl.scrollViewer.ScrollToHorizontalOffset((double)e.NewValue); } } private void scrollBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (scrollViewer != null) { scrollViewer.ScrollToHorizontalOffset((double)e.NewValue); } } protected override void OnRenderSizeChanged(SizeChangedInfo info) { base.OnRenderSizeChanged(info); //SetScrollBar(); } /// /// 设置滚动条 /// private void SetScrollBar() { var uielement = this.SelectedContent as UIElement; if (uielement != null) { scrollViewer = FindVisualChild(uielement); } if (scrollViewer != null && scrollBar != null) { //scrollBar.Value = scrollViewer.HorizontalOffset; //scrollBar.Maximum = scrollViewer.ScrollableWidth; //scrollBar.ViewportSize = scrollViewer.ViewportWidth; ViewportWidth = scrollViewer.ViewportWidth; ScrollableWidth = scrollViewer.ScrollableWidth; HSValue = scrollViewer.HorizontalOffset; } } /// /// 从父容器中查找指定类型的控件 /// /// /// /// private T FindVisualChild(DependencyObject parent) where T : DependencyObject { if (parent == null) return null; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var childObject = VisualTreeHelper.GetChild(parent, i); if (childObject == null) return null; var child = childObject as T; if (child == null) { var childItem = FindVisualChild(childObject); if (childItem != null) return childItem; } return child; } return null; } /// /// 查找指定类型的父容器 /// /// /// The child. /// ``0. private static T FindVisualParent(DependencyObject child) where T : DependencyObject { if (child == null) return null; var parentObject = VisualTreeHelper.GetParent(child); if (parentObject == null) return null; var parent = parentObject as T; return parent ?? FindVisualParent(parentObject); } } }