前几个星期做了个WPF的项目,也学习了一些WPF 的知识,自己也整理了一下,可能有点乱,请见谅,有什么错误也请大家指出来
各类模板
ContentControl族
派生自ContentControl类 里面的content都是单一的 内容属性名为content
HeaderContentControl族
派生自HeaderedContentControl类 HeaderedContentControl是ContentControl类的派生类
用于显示带标题的数据 内容属性为content和Header 并且只能容纳一个属性作为内容
ItemControl族
派生自ItemControl类 内容属性为Item或ItemSource 每种ItemsControl都对应有自己的条目容器(Item Container)
HeaderedItemsControl族
均派生自HeaderedItemsContrl类 用于显示列表化的控件 内容属性为 Item ItemSource 和Header 本族控件 :MenuItem TreeViewItem ToolBar
Decorator类
均派生自Decorator类 起UI装饰作用 内容属性为Child 只能由单一元素充当CHild
Sharp族
均派生自Sharp类 用于2D图形绘制 无内容属性 使用FIll填充 Stroke属性设置边线
Panel族
派生自panel抽象类 主要功能是UI布局 内容属性为Children 内容可以是多个元素。
DataTemplate ControlTemplate
1. ControlTemplate用来指定 Control 的可在其多个实例之间共享的可视结构,行为,和Trigger等方面。和创建自定义控件不同,在许多情况下,您都不需要编写自己的控件,您只是希望更改控件的可视化或替换现有控件的 ControlTemplate。使用ControlTemplate很简单,只需要设定它,然后赋值到Template属性下面即可。
2. DataTemplate用来描述数据对象的可视结构。通常使用DataTemplate 指定数据的直观表示。使用DataTemplate很简单,只需要设定它,然后赋值到CellTemplate, ContentTemplate, ItemTemplate属性下面即可.
1. ControlTemplate用于描述控件本身的视觉样式和行为. 使用TemplateBinding来绑定控件自身的属性, 比如{TemplateBinding Background}。
2. DataTemplate用于描述控件的Content(数据对象)的视觉样式。 使用Binding来绑定数据对象的属性, 比如{Binding PersonName}。即ControlTemplate决定了控件本身的样子。DataTemplate决定了Content的样子。
一般来说, ControlTemplate内有一个ContentPresenter, 这个ContentPresenter的ContentTemplate就是DataTemplate类型:
Control类型
- Template属性 (ControlTemplate类型)
- ContentPresenter
- ContentTemplate (DataTemplate类型)
ContentControl类型
- Template属性 (ControlTemplate类型) 继承自Control
- ContentTemplate (DataTemplate类型)
ItemsControl类型
- Template属性 (ControlTemplate类型) 继承自Control
- ItemsPanel属性 (ItemsPanelTemplate类型) 指定布局容器
- ItemTemplate属性 (DateTemplate类型) 每个Item的Template
数据绑定
Binding是数据绑定绑定两个数据,能够把源数据传达给目标,如果当源数据发生改变时,想让目标的数据也跟着发生变化,那这个类需要实现INotifyProperty接口并且在set语句中激发propertyChange事件
Public class PropertyChange :INotifyPropertyChange
{
Private string name;
Public event PropertyChangeEventHandler PropertyChanged;
Public string Name{
Get
{ return this.name;}
Set{
This.name = value;
If(this.PropertyChanged !=null)
this.PropertyChanged.Invoke(this, New PropertyChangeEventArgs(“Name”));
}
}
}
}
当name值发生改变后 就会触发PorpertyChanged事件
<TextBox Text= {Binding Path=xx,Mode = OneWay}/>
Mode代表binding的方向
oneWay:使用 OneWay 绑定时,每当源发生变化,数据就会从源流向目标。
OneTime: 绑定也会将数据从源发送到目标;但是,仅当启动了应用程序或 DataContext 发生更改时才会如此操作,因此,它不会侦听源中的更改通知。
OneWayToSource: 绑定会将数据从目标发送到源。
TwoWay: 绑定会将源数据发送到目标,但如果目标属性的值发生变化,则会将它们发回给源。
Default: binding的模式根据实际情况来定,如果是可编辑的就是TwoWay,只读的就是OneWay.
后台绑定数据有两种方式
this.TextBox1.SetBinding(TextBox.TextProperty, new Binding(“Name”){Source=xxxx});
或者BindingOperation.SetBindng(this.TextBox1,TextBox.TextProperty,new Binding(){});
没有Path的binding
有些时候,你会看到Path是一个“.”或者干脆没有(C#后台代码必须要有.)。这是因为源本身就是数据,想String和Int,这时候我们只需要将path的值设置成“.”就行了。
为Binding指定源(Source)的几种方法
普通的单个对象来指定为Source: 如果实现了INotifyPropertyChanged接口,则可通过在属性的Set语句中激发PropertyChanged事件即可通知Binding 数据已经更新。
把普通的CLR集合类型对象指定为Source,包括数组,List<T>,ObservableCollention<T>
ADO.Net数据对象指定为source。包括DataTable和DataView
使用XmlDataProvider把Xml数据指定为Source。
把依赖对象(dependency Object)指定为Source: 这个既可以做源又可以做目标
把容器的DataContext指定为Source(WPF Data Binding的默认行为):
通过ElementName指定Source
通过Binding的RelativeSource属性相对的指定Source:当控件需要关注自己的,自己容器的或者自己内部元素的某个值就要用这种方法。
把ObjectDataProvider对象指定为Source:当数据源的数据不是通过属性而是通过方法暴露给外界的时候,就可以使用这个对象来包装数据源再把他们定位Source。
使用Linq检索到的数据对象作为Binding的源
this.DataGrid.ItemSource = list;
Binding bind= new Binding(“SelectedItem.xx”){source= DataGrid};
this.Combox.setBinding(Combox.DisPlayValuePathProperty , bind);
没有source只有Path的binding 空间会沿着父控件一级一级往上找 找DataContext属性 直到找到为止
依赖属性 附加属性
依赖属性 Public class Student:DependencyObject
{
Public static readonly DependencyProperty NameProperty = DependencyProperty.Register(“Name”,typeof(string),typeOf(Student));
}
有这么一个依赖属性后就可以使用它的 setValue和getValue 方法了
比如 Student stu =new Student();
stu.setValue(Student.NameProperty,this.TextBox.Text);
This.TextBox1.Text = (String)stu.getValue(Student.NameProperty);
getValue取出来的数据是Object类型 需要做一下转换。
BindingOperation.setBinding(stu,Student.NameProperty,Binding());
附加属性
Public static readonly DependencyProperty GradeProperty = DependencyProperty.RegisterAttached(“Grade” , typeof(int),typeof(Student),new UIPropertymetadata(0));
线程
WPF主线程是UI线程,使用Timer每个事件会执行,开辟新线程,DispatcherTimer 事件会放到一个队列上一个一个执行还是在主线程。 所以在Timer事件中不能访问主界面中的控件。不过DispatcherTimer里面可能执行等待动作或者时间过长,可能会导致UI假死,Timer就是执行比较快
Timer
//更新日志和交易记录定时器
System.Timers.Timer t = new System.Timers.Timer();//定时器
t.Interval = 2000;//设置定时器时间间隔(毫秒)
t.Elapsed += new System.Timers.ElapsedEventHandler(FreshLogs);//到达时间的时候执行事件
t.AutoReset = true;//设置是执行一次(false)还是一直执行(true)
t.Enabled = true;//是否执行System.Time--rs.Timer.Elapsed事件
TimeDispatcher DispatcherTimer time = new DispatcherTimer();
time.Interval = TimeSpan.FromSeconds(2);
time.Tick += new EventHandler(Timer);
time.Start();
不过可以在Timer中使用 invoke或者BeginInvoke的方法进行更新UI界面元素
MainWindow.dataGrid.Dispatcher.BeginInvoke(new Action(MainWindow.Refelsh), System.Windows.Threading.DispatcherPriority.SystemIdle);
public static void Reflesh()
{
i = i + 1;
dataGrid.Content = i;
for (int iii = 0; iii < 100000000; iii++)
{
}
MessageBox.Show("里面完成");
}
Invoke是同步的BeginInvoke是异步的 DispatcherPriority是一个枚举值
| 枚举值为 -1。 这是一个无效的优先级。 | ||
| Inactive | 枚举值为 0。不处理操作。 | |
| SystemIdle | 枚举值为 1。在系统空闲时处理操作。 | |
| ApplicationIdle | 枚举值为 2。在应用程序空闲时处理操作。 | |
| ContextIdle | 枚举值为 3。在后台操作完成后处理操作。 | |
| Background | 枚举值为 4。在完成其他所有非空闲操作后处理操作。 | |
| Input | 枚举值为 5。按输入的优先级处理操作。 | |
| Loaded | 枚举值为 6。在布局和呈现完成后即将为输入优先级的项目提供服务时处理操作。具体来说,此值在引发 Loaded 事件时使用。 | |
| Render | 枚举值为 7。按呈现的优先级处理操作。 | |
| DataBind | 枚举值为 8。按数据绑定的优先级处理操作。 | |
| Normal | 枚举值为 9。按正常优先级处理操作。 这是典型的应用程序优先级。 | |
| Send | 枚举值为 10。在处理其他异步操作前处理操作。 这是最高优先级。 |
先写到这,这些是自己整理的,后面还会发