WPF教程005 - Timeline时间轴控件的实现

效果图:

由于整个控件是实现之后才写的教程,因此这里记录的代码是最终实现后的,前后会引用到其他的一些依赖属性或者代码,需要阅读整篇文章。

1、确定Timeline继承的基类

从效果图中可以看到,时间轴都是由一节一节的子节点组成的,这个很容易联想到我们应该将Timeline继承自ItemsControl。之外仔细观察效果图,可以发现第一项的时间轴节点与其他都不同,而且拆解每一个子项,发现都是由一个圆圈和一个竖线组成,但是最后一项和上面的都不同,少了一个竖线,因此为了控制这些样式,我们需要重新定义一个TimelineItem,将其继承自ContentControl,来重新定义逻辑。

2、具体实现

2.1、TimelineItem的具体实现
2.1.1、设计思路

2.1.1.1、为了能确定当前子项所处的位置(是第一项、中间项还是最后一项),我能想到的有下面2种实现方式

①、使用Converter转换器,将当前Item传入后台的转换器种,通过ItemsControl自带的【ItemContainerGenerator.IndexFromContainer】方法获取到当前Item的Index,然后将Index与ItemsControl的Items进行比较,判断当前Item的所处位置。

②、直接在TimelineItem类里面定义3个依赖属性:IsFirstItem、IsMiddleItem、IsLastItem,来定义TimelineItem的身份,这样我们就可以在触发器里面根据这些属性来进行一些样式上面的设置,就像使用IsMouseOver属性一样。

接下来的代码示例中,我采用了第二种实现方式(因为第一种我已经用过了^_^)

2.1.1.2、为了控件的灵活性以及用户可能需要自定义第一项、中间项、最后一项的样式,或者更极端一点,用户可能会自定义每一个Item的外观,因此在Timeline类里面定义了好几个依赖属性:FirstSlotTemplate、MiddleSlotTemplate、LastSlotTemplate、IsCustomEverySlot以及SlotTemplate。

2.1.2、具体代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
namespace ZdfFlatUI
{
    public class TimelineItem : ContentControl
    {
        #region DependencyProperty
        #region IsFirstItem
        /// <summary>
        /// 获取或者设置该项在列表中是否是第一个
        /// </summary>
        [Bindable(true), Description("获取或者设置该项在列表中是否是第一个")]
        public bool IsFirstItem
        {
            get { return (bool)GetValue(IsFirstItemProperty); }
            set { SetValue(IsFirstItemProperty, value); }
        }

        public static readonly DependencyProperty IsFirstItemProperty =
            DependencyProperty.Register("IsFirstItem", typeof(bool), typeof(TimelineItem), new PropertyMetadata(false));
        #endregion
        #region IsMiddleItem
        /// <summary>
        /// 获取或者设置该项在列表中是否是中间的一个
        /// </summary>
        [Bindable(true), Description("获取或者设置该项在列表中是否是中间的一个")]
        public bool IsMiddleItem
        {
            get { return (bool)GetValue(IsMiddleItemProperty); }
            set { SetValue(IsMiddleItemProperty, value); }
        }
        public static readonly DependencyProperty IsMiddleItemProperty =
            DependencyProperty.Register("IsMiddleItem", typeof(bool), typeof(TimelineItem), new PropertyMetadata(false));
        #endregion
        #region IsLastItem
        /// <summary>
        /// 获取或者设置该项在列表中是否是最后一个
        /// </summary>
        [Bindable(true), Description("获取或者设置该项在列表中是否是最后一个")]
        public bool IsLastItem
        {
            get { return (bool)GetValue(IsLastItemProperty); }
            set { SetValue(IsLastItemProperty, value); }
        }

        public static readonly DependencyProperty IsLastItemProperty =
            DependencyProperty.Register("IsLastItem", typeof(bool), typeof(TimelineItem), new PropertyMetadata(false));
        #endregion
        #endregion
        #region Constructors
        static TimelineItem()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TimelineItem), new FrameworkPropertyMetadata(typeof(TimelineItem)));
        }
        #endregion
    }
}

Timeline代码

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Collections.Specialized;
  4 using System.Linq;
  5 using System.Text;
  6 using System.Windows;
  7 using System.Windows.Controls;
  8 using System.ComponentModel;
  9 namespace ZdfFlatUI
 10 {
 11     /// <summary>
 12     /// 时间轴
 13     /// </summary>
 14     /// <remarks>add by zhidanfeng 2017.5.29</remarks>
 15     public class Timeline : ItemsControl
 16     {
 17         #region private fields
 18         #endregion
 19         #region DependencyProperty
 20         #region FirstSlotTemplate
 21         /// <summary>
 22         /// 获取或者设置第一个时间轴点的样子
 23         /// </summary>
 24         [Bindable(true), Description("获取或者设置第一个时间轴点的样子")]
 25         public DataTemplate FirstSlotTemplate
 26         {
 27             get { return (DataTemplate)GetValue(FirstSlotTemplateProperty); }
 28             set { SetValue(FirstSlotTemplateProperty, value); }
 29         }
 30
 31         public static readonly DependencyProperty FirstSlotTemplateProperty =
 32             DependencyProperty.Register("FirstSlotTemplate", typeof(DataTemplate), typeof(Timeline));
 33         #endregion
 34         #region MiddleSlotTemplate
 35         /// <summary>
 36         /// 获取或者设置中间的时间轴点的样子
 37         /// </summary>
 38         [Bindable(true), Description("获取或者设置中间的时间轴点的样子")]
 39         public DataTemplate MiddleSlotTemplate
 40         {
 41             get { return (DataTemplate)GetValue(MiddleSlotTemplateProperty); }
 42             set { SetValue(MiddleSlotTemplateProperty, value); }
 43         }
 44
 45         public static readonly DependencyProperty MiddleSlotTemplateProperty =
 46             DependencyProperty.Register("MiddleSlotTemplate", typeof(DataTemplate), typeof(Timeline));
 47         #endregion
 48         #region LastItemTemplate
 49         /// <summary>
 50         /// 获取或者设置最后一个时间轴点的样子
 51         /// </summary>
 52         [Bindable(true), Description("获取或者设置最后一个时间轴点的样子")]
 53         public DataTemplate LastSlotTemplate
 54         {
 55             get { return (DataTemplate)GetValue(LastSlotTemplateProperty); }
 56             set { SetValue(LastSlotTemplateProperty, value); }
 57         }
 58
 59         public static readonly DependencyProperty LastSlotTemplateProperty =
 60             DependencyProperty.Register("LastSlotTemplate", typeof(DataTemplate), typeof(Timeline));
 61         #endregion
 62         #region IsCustomEverySlot
 63         /// <summary>
 64         /// 获取或者设置是否自定义每一个时间轴点的外观。
 65         /// </summary>
 66         [Bindable(true), Description("获取或者设置是否自定义每一个时间轴点的外观。当属性值为True时,FirstSlotTemplate、MiddleSlotTemplate、LastSlotTemplate属性都将失效,只能设置SlotTemplate来定义每一个时间轴点的样式")]
 67         public bool IsCustomEverySlot
 68         {
 69             get { return (bool)GetValue(IsCustomEverySlotProperty); }
 70             set { SetValue(IsCustomEverySlotProperty, value); }
 71         }
 72
 73         public static readonly DependencyProperty IsCustomEverySlotProperty =
 74             DependencyProperty.Register("IsCustomEverySlot", typeof(bool), typeof(Timeline), new PropertyMetadata(false));
 75         #endregion
 76         #region SlotTemplate
 77         /// <summary>
 78         /// 获取或者设置每个时间轴点的外观
 79         /// </summary>
 80         [Bindable(true), Description("获取或者设置每个时间轴点的外观。只有当IsCustomEverySlot属性为True时,该属性才生效")]
 81         public DataTemplate SlotTemplate
 82         {
 83             get { return (DataTemplate)GetValue(SlotTemplateProperty); }
 84             set { SetValue(SlotTemplateProperty, value); }
 85         }
 86
 87         public static readonly DependencyProperty SlotTemplateProperty =
 88             DependencyProperty.Register("SlotTemplate", typeof(DataTemplate), typeof(Timeline));
 89         #endregion
 90         #endregion
 91         #region Constructors
 92         static Timeline()
 93         {
 94             DefaultStyleKeyProperty.OverrideMetadata(typeof(Timeline), new FrameworkPropertyMetadata(typeof(Timeline)));
 95         }
 96         #endregion
 97         #region Override
 98         protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
 99         {
100             int index = this.ItemContainerGenerator.IndexFromContainer(element);
101             TimelineItem timelineItem = element as TimelineItem;
102             if(timelineItem == null)
103             {
104                 return;
105             }
106             if(index == 0)
107             {
108                 timelineItem.IsFirstItem = true;
109             }
110             if(index == this.Items.Count - 1)
111             {
112                 timelineItem.IsLastItem = true;
113             }
114             base.PrepareContainerForItemOverride(timelineItem, item);
115         }
116         protected override DependencyObject GetContainerForItemOverride()
117         {
118             return new TimelineItem();
119         }
120         public override void OnApplyTemplate()
121         {
122             base.OnApplyTemplate();
123         }
124         protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
125         {
126             base.OnItemsChanged(e);
127             //以下代码是为了新增项或者移除项时,正确设置每个Item的外观
128             switch (e.Action)
129             {
130                 case NotifyCollectionChangedAction.Add:
131                     if (e.NewStartingIndex == 0) //如果新添加项是放在第一位,则更改原来的第一位的属性值
132                     {
133                         this.SetTimelineItem(e.NewStartingIndex + e.NewItems.Count);
134                     }
135                     //如果新添加项是放在最后一位,则更改原来的最后一位的属性值
136                     if (e.NewStartingIndex == this.Items.Count - e.NewItems.Count)
137                     {
138                         this.SetTimelineItem(e.NewStartingIndex - 1);
139                     }
140                     break;
141                 case NotifyCollectionChangedAction.Remove:
142                     if(e.OldStartingIndex == 0) //如果移除的是第一个,则更改更新后的第一项的属性值
143                     {
144                         this.SetTimelineItem(0);
145                     }
146                     else
147                     {
148                         this.SetTimelineItem(e.OldStartingIndex - 1);
149                     }
150                     break;
151             }
152         }
153         #endregion
154         #region private function
155         /// <summary>
156         /// 设置TimelineItem的位置属性
157         /// </summary>
158         /// <param name="index"></param>
159         private void SetTimelineItem(int index)
160         {
161             if(index > this.Items.Count || index < 0)
162             {
163                 return;
164             }
165             TimelineItem timelineItem = this.ItemContainerGenerator.ContainerFromIndex(index) as TimelineItem;
166             if(timelineItem == null)
167             {
168                 return;
169             }
170             timelineItem.IsFirstItem = index == 0;
171             timelineItem.IsLastItem = index == this.Items.Count - 1;
172             timelineItem.IsMiddleItem = index > 0 && index < this.Items.Count - 1;
173         }
174         #endregion
175     }
176 }

样式代码:

  1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  2                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ZUI="clr-namespace:ZdfFlatUI">
  3     <PathGeometry x:Key="Icon_Gou" Figures="M378.410667 850.450963C364.491852 850.450963 350.610963 845.293037 340.02963 834.939259L20.920889 523.529481C-0.279704 502.821926-0.279704 469.295407 20.920889 448.587852 42.121481 427.880296 76.48237 427.880296 97.682963 448.587852L378.410667 722.526815 925.75763 188.491852C946.958222 167.784296 981.319111 167.784296 1002.519704 188.491852 1023.720296 209.161481 1023.720296 242.688 1002.519704 263.395556L416.791704 834.939259C406.172444 845.293037 392.291556 850.450963 378.410667 850.450963L378.410667 850.450963Z" />
  4     <DataTemplate x:Key="FirstSlotTemplate">
  5         <Grid>
  6             <Ellipse x:Name="Slot1" Width="15" Height="15" Fill="#30AAADAF" />
  7             <Ellipse x:Name="Slot2" Width="7" Height="7" Fill="#FF6501" />
  8         </Grid>
  9     </DataTemplate>
 10     <DataTemplate x:Key="LastSlotTemplate">
 11         <Grid>
 12             <Ellipse x:Name="Slot1" Width="15" Height="15" Fill="#AAADAF" />
 13             <Path x:Name="path" Width="9"
 14                   Data="{StaticResource Icon_Gou}"
 15                   Fill="#FFFFFF" Stretch="Uniform" />
 16         </Grid>
 17     </DataTemplate>
 18     <Style TargetType="{x:Type ZUI:TimelineItem}">
 19         <Setter Property="Background" Value="Transparent" />
 20         <Setter Property="BorderBrush" Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 21         <Setter Property="BorderThickness" Value="0" />
 22         <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 23         <Setter Property="Padding" Value="15,0,15,0" />
 24         <Setter Property="MinHeight" Value="50" />
 25         <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 26         <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 27         <Setter Property="SnapsToDevicePixels" Value="True" />
 28         <Setter Property="UseLayoutRounding" Value="True" />
 29         <Setter Property="Template">
 30             <Setter.Value>
 31                 <ControlTemplate TargetType="{x:Type ZUI:TimelineItem}">
 32                     <Grid>
 33                         <Grid.RowDefinitions>
 34                             <RowDefinition Height="auto" />
 35                             <RowDefinition Height="*" />
 36                         </Grid.RowDefinitions>
 37                         <Grid.ColumnDefinitions>
 38                             <ColumnDefinition Width="auto" />
 39                             <ColumnDefinition Width="*" />
 40                         </Grid.ColumnDefinitions>
 41                         <ContentPresenter x:Name="Slot" ContentTemplate="{Binding MiddleSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 42                         <Rectangle x:Name="Line" Grid.Row="1" Width="1"
 43                                    Fill="{TemplateBinding BorderBrush}" />
 44                         <ContentPresenter Grid.RowSpan="2" Grid.Column="1"
 45                                           Margin="{TemplateBinding Padding}"
 46                                           HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
 47                                           VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
 48                     </Grid>
 49                     <ControlTemplate.Triggers>
 50                         <!--
 51                             当IsCustomEverySlot为True时,FirstSlotTemplate、MiddleSlotTemplate、LastSlotTemplate都将失效,
 52                             只能设置SlotTemplate来定义每一个时间轴点的样式
 53                         -->
 54                         <MultiDataTrigger>
 55                             <MultiDataTrigger.Conditions>
 56                                 <Condition Binding="{Binding IsFirstItem, RelativeSource={RelativeSource Self}}" Value="True" />
 57                                 <Condition Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="False" />
 58                             </MultiDataTrigger.Conditions>
 59                             <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding FirstSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 60                         </MultiDataTrigger>
 61                         <MultiDataTrigger>
 62                             <MultiDataTrigger.Conditions>
 63                                 <Condition Binding="{Binding IsLastItem, RelativeSource={RelativeSource Self}}" Value="True" />
 64                                 <Condition Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="False" />
 65                             </MultiDataTrigger.Conditions>
 66                             <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding LastSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 67                         </MultiDataTrigger>
 68                         <MultiDataTrigger>
 69                             <MultiDataTrigger.Conditions>
 70                                 <Condition Binding="{Binding IsMiddleItem, RelativeSource={RelativeSource Self}}" Value="True" />
 71                                 <Condition Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="False" />
 72                             </MultiDataTrigger.Conditions>
 73                             <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding MiddleSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 74                         </MultiDataTrigger>
 75                         <DataTrigger Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="True">
 76                             <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding SlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" />
 77                         </DataTrigger>
 78                         <Trigger Property="IsLastItem" Value="True">
 79                             <Setter TargetName="Line" Property="Visibility" Value="Collapsed" />
 80                         </Trigger>
 81                         <Trigger Property="IsMiddleItem" Value="True">
 82                             <Setter TargetName="Line" Property="Visibility" Value="Visible" />
 83                         </Trigger>
 84                     </ControlTemplate.Triggers>
 85                 </ControlTemplate>
 86             </Setter.Value>
 87         </Setter>
 88     </Style>
 89     <Style TargetType="{x:Type ZUI:Timeline}">
 90         <Setter Property="Background" Value="Transparent" />
 91         <Setter Property="BorderBrush" Value="#F0F0F0" />
 92         <Setter Property="BorderThickness" Value="0" />
 93         <Setter Property="Foreground" Value="Black" />
 94         <Setter Property="HorizontalContentAlignment" Value="Left" />
 95         <Setter Property="VerticalContentAlignment" Value="Top" />
 96         <Setter Property="SnapsToDevicePixels" Value="True" />
 97         <Setter Property="UseLayoutRounding" Value="True" />
 98         <Setter Property="FirstSlotTemplate" Value="{StaticResource FirstSlotTemplate}" />
 99         <Setter Property="MiddleSlotTemplate" Value="{StaticResource LastSlotTemplate}" />
100         <Setter Property="LastSlotTemplate" Value="{StaticResource LastSlotTemplate}" />
101         <Setter Property="Template">
102             <Setter.Value>
103                 <ControlTemplate TargetType="{x:Type ZUI:Timeline}">
104                     <Border Background="{TemplateBinding Background}"
105                             BorderBrush="{TemplateBinding BorderBrush}"
106                             BorderThickness="{TemplateBinding BorderThickness}"
107                             SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
108                             UseLayoutRounding="{TemplateBinding UseLayoutRounding}">
109                         <ZUI:ZScrollViewer>
110                             <ItemsPresenter />
111                         </ZUI:ZScrollViewer>
112                     </Border>
113                 </ControlTemplate>
114             </Setter.Value>
115         </Setter>
116     </Style>
117 </ResourceDictionary>

在Timeline类中,有几处关键代码

①、为了能将TimelineItem和Timeline关联起来,需要重写【GetContainerForItemOverride】方法

protected override DependencyObject GetContainerForItemOverride()
{
	return new TimelineItem();
}

②、在控件第一次初始化以及在后来的新增时,需要设置TimelineItem的几个依赖属性值,即设置Item具体是第一个、中间项还是最后一项,因此需要重写【PrepareContainerForItemOverride】

protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
	int index = this.ItemContainerGenerator.IndexFromContainer(element);
	TimelineItem timelineItem = element as TimelineItem;
	if(timelineItem == null)
	{
		return;
	}
	if(index == 0)
	{
		timelineItem.IsFirstItem = true;
	}
	if(index == this.Items.Count - 1)
	{
		timelineItem.IsLastItem = true;
	}
	base.PrepareContainerForItemOverride(timelineItem, item);
}

③、Timeline控件在运行过程中,可能会涉及到新增或者删除节点,这时同样需要实时的设置每个TimelineItem的IsFirstItem、IsMiddleItem、IsLastItem,这样呈现正确的外观

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
	base.OnItemsChanged(e);
	//以下代码是为了新增项或者移除项时,正确设置每个Item的外观
	switch (e.Action)
	{
		case NotifyCollectionChangedAction.Add:
			if (e.NewStartingIndex == 0) //如果新添加项是放在第一位,则更改原来的第一位的属性值
			{
				this.SetTimelineItem(e.NewStartingIndex + e.NewItems.Count);
			}
			//如果新添加项是放在最后一位,则更改原来的最后一位的属性值
			if (e.NewStartingIndex == this.Items.Count - e.NewItems.Count)
			{
				this.SetTimelineItem(e.NewStartingIndex - 1);
			}
			break;
		case NotifyCollectionChangedAction.Remove:
			if(e.OldStartingIndex == 0) //如果移除的是第一个,则更改更新后的第一项的属性值
			{
				this.SetTimelineItem(0);
			}
			else
			{
				this.SetTimelineItem(e.OldStartingIndex - 1);
			}
			break;
	}
}

最终效果图:

代码下载:https://github.com/zhidanfeng/WPF.UI

时间: 2024-10-03 09:04:29

WPF教程005 - Timeline时间轴控件的实现的相关文章

SNF开发平台WinForm之十三-时间轴控件使用-SNF快速开发平台3.3-Spring.Net.Framework

一.显示效果如下: 二.在控件库里选择UCTimeAxis 拖拽到窗体里. 三.加入以下代码,在load事件里进行调用就可以运行了. #region 给时间轴控件加载数据 private void UCTimeAxisData() { //增加节点 List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); list.Add(new KeyValueP

都昌时间轴控件功能说明

这里展示了使用都昌时间轴控件(DCTimeLine)展示手术排程结果,淡绿色部分是已经开始或者完成的手术,红色为病人死亡的手术,灰色为正在排队中的手术.用户点击手术色块,控件能触发一个事件,应用程序编程响应事件显示对应手术的详细信息.本控件仅仅用于展示已有的手术排程结果,不管手术排程过程.具体如何排程请咨询其他人士. 其他应用 诚邀各位专家点评,提出建议,以帮助我们持续改进,不断进步.我们产品网站 www.dcwriter.cn,联系邮箱 [email protected]

老猪带你玩转自定义控件三——sai大神带我实现ios 8 时间滚轮控件

ios 8 的时间滚轮控件实现了扁平化,带来很好用户体验,android没有现成控件,小弟不才,数学与算法知识不过关,顾十分苦恼,幸好在github上找到sai大神实现代码,甚为欣喜,顾把学习这个控件点滴记录下来,分享给大家.项目原地址https://github.com/saiwu-bigkoo/Android-PickerView. ios 8 滚轮的效果: 而sai大神控件的效果: 哎,妈呀是不是效果95%相识啊. 好了,废话少说,谈谈我从这个控件中收获的心得. 首先,我们要高瞻远瞩看一下

[转载]ExtJs4 笔记(8) Ext.slider 滚轴控件、 Ext.ProgressBar 进度条控件、 Ext.Editor 编辑控件

作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/)版权声明:本文的版权归作者与博客园共有.转载时须注明本文的详细链接,否则作者将保留追究其法律责任. 本篇要登场的有三个控件,分别是滚轴控件.进度条控件和编辑控件. 一.滚轴控件 Ext.slider 1.滚轴控件的定义 下面我们定义三个具有代表意义滚轴控件,分别展示滚轴横向.纵向,以及单值.多值选择的特性: [html] <h1>滚轴控件</h1> <div class

WPF中不规则窗体与WindowsFormsHost控件的兼容问题完美解决方案

首先先得瑟一下,有关WPF中不规则窗体与WindowsFormsHost控件不兼容的问题,网上给出的解决方案不能满足所有的情况,是有特定条件的,比如  WPF中不规则窗体与WebBrowser控件的兼容问题解决办法.该网友的解决办法也是别出心裁的,为什么这样说呢,你下载了他的程序认真读一下就便知道,他的webBrowser控件的是单独放在一个Form中,让这个Form与WPF中的一个Bord控件进行关联,进行同步移动,但是在移动的时候会出现闪烁,并且还会出现运动的白点,用户体验肯定不好. OK,

WPf 带滚动条WrapPanel 自动换行 和控件右键菜单

原文:WPf 带滚动条WrapPanel 自动换行 和控件右键菜单 技能点包括 WPf 样式的引用 数据的验证和绑定 比较适合初学者 前台: <Window.Resources> <local:PathToSource x:Key="n2"/> <Style x:Key="{x:Type ContextMenu}" TargetType="{x:Type ContextMenu}"> <Setter Pr

【WPF学习】第二十章 内容控件

原文:[WPF学习]第二十章 内容控件 内容控件(content control)是更特殊的控件类型,它们可包含并显示一块内容.从技术角度看,内容控件时可以包含单个嵌套元素的控件.与布局容器不同的是,内容控件只能包含一个子元素,而布局容器主要愿意可以包含任意多个牵头元素. 正如前面所介绍,所有WPF布局容器都继承自抽象类Panel,该类提供了对包含多个元素的支持.类似地,所有内容控件都继承自抽象类ContentControl.下图显示了ContentControl类的层次结构. 图 Conten

mui 时间日期控件(浏览器上无法查看,在手机端可以点击)

<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <title></title> <link href="css/mui.mi

WPF布局之让你的控件随着窗口等比放大缩小,适应多分辨率满屏填充应用

一直以来,我们设计windows应用程序,都是将控件的尺寸定好,无论窗体大小怎么变,都不会改变,这样的设计对于一般的应用程序来说是没有问题的,但是对于一些比较特殊的应用,比如有背景图片的,需要铺面整个屏幕,由于存在多种不同的分辨率,所以会出现布局混乱的情况.今天我们来看看WPF中如何让我们的控件也随着分辨率放大缩小.下面来写一个例子看看效果吧~  一.普通布局中的问题 这里我们写一个简单的页面,新建WPF项目,在MainWindow里面添加按钮,如下图: 这个页面很简单,只有三个按钮,我们想的是