wpf和winform
winform -> 新建windows窗体程序
控件的描述全在一个Designer
的cs文件中,控件事件则在对应的cs文件里。
wpf -> 新建wpf程序
感觉winform就是基于mfc再封装了一层c#,界面设计等还是wpf吧
代码隐藏文件
界面描述放在xaml
文件里的
为界面增加功能(事件呀等)的cs代码,就放入.xaml.cs
文件中
隐藏文件默认是放入xaml文件同一个目录中的。
界面第一句:
路由事件
路由事件有点想mfc的common,但是它要多点。
lbutondown这些事件是标准事件,它只会发给被显示订阅的控件。
像keydown这种路由事件它会:
先走下钻事件(Preview开头的事件),再走上钻事件(正常开头的事件);
pre的Window事件->pre的Grid网格事件->pre的焦点控件事件->焦点控件事件->Grid网格事件->Window事件
如需要停止路由,直接e.Handled = true;
布局控件
把这几个基本的布局控件搞了,就直接干代码了。太麻烦了!!
Canvas控件
书上说这个可以完全自由地对控件的位置进行安排,且HorizontalAligment
和VerticalAlignment
并不能改变这些元素位置
测试发现,窗口的变大变小如果是Grid则会跟随变化里面子控件的大小;而Canvas则不会,里面的子控件大小位置被固定了似的。
可以用Canvas.Top
等这些属性来限定子控件在Canvas
里面的布局,但我估计实际应用慢慢看吧。。。。
DockPanel控件
它会从上往下(越接近顶层,越优先)。布局子控件,除非有限制(height、width),不然会尽量布满布局。
它是从剩余空间来进行计算(DockPanel.Dock="Top"
以剩余的上半部分为基础)
StackPanel控件
它的设置更多的设置本身,它来控制内部子控件的堆叠方向,不会占满布局。
用Orientaion、VerticalAlignment、HorizontalAlignment
来设置内部控件的堆叠方向、内部控件对齐方向。
WrapPanel控件
是StackPanel的扩展版本;容纳不下的控件会被安排到下一行
Grid控件
透明窗口
|
|
控件标题内容换行
|
|
如上,很方便。但还是纠结了,本来Windows换行符是\r\n
的,c#代码换行也是如此。
于是有下:
空格 ( )
Tab ( )
回车 (
) 难怪上面是13
换行 (
)
高宽百分比设置
今天试了下,发现 Height和Width 不仅可以用数字表示,还可以 30*
这种百分比表示。
这样的话就会把所有子控件的加上,再除以相应数字。得出百分比,进行布局设置。
grid跨行跨列
对于grid可以分区:
但是当有个控件比较特殊,需要占多个行或列时(上面grid划分好了的行和列)
就可以使用Grid.RowSpan(列同理)
它会从 Grid.Row(列同理)
开始,占满接下来几个的行(列)
x命名空间
tab控件使用
注意TabItem子控件只能有一个,所以一般用布局控件来代替。
x:Name和Name
所有的Type在xaml中都能使用x:Name,即使这个type 没有定义一个叫着Name的Property。
因为xmal会在后台为其分配一个field来存储,以便在Binding等里面使用。
像FrameworkElement, VisualStateGroup的某些type,我们在xaml中可以使用Name来代替x:Name,
因为它们定义了Name Property,但是最关键的是在type上声明了一个Attribute,[RuntimeNameProperty(“Name”)],
正是这个attribute把Name映射到了x:Name上,所以让Name可以做到x:Name的功能。
正因为如此,name属性超级好用,在xaml给个name属性,相应的隐藏文件就可以直接使用此name来代表此控件
数据绑定
https://www.tutorialspoint.com/wpf
https://msdn.microsoft.com/zh-cn/library/ms752347(v=vs.110).aspx
Content="{Binding}"
默认关联属性.aspx)
本地对象绑定
如上所说,绑定和Name
相关。
先看本地对象绑定:
先看Label
的绑定,Binding
通过ElementName
的Name
属性找到了CheckBox
对象,并绑定到它身上,再通过IsChecked
属性来传值。实际效果:check选中,label就enable(相反同理)
再看TextBox
绑定,Binding
还是绑定到ComboBox
上,且它文本绑定到了选中的内容上。实际效果:ComboBox
选中哪项,TextBox
就显示相应的选中内容。
静态绑定到外部对象
|
|
如上,向combobox添加了三个选项,但是TextBox
的内部绑定却不得不改了,我也不知道。。想说绑定规则太多了。。。
Mode的类型
Mode = OneWay 就仅仅只是绑定,控件修改的数据也不会更新到绑定对象里面去
Mode = TwoWay 绑定后,若控件修改了数据也会更新到绑定的对象上面去。
Mode = OneWayToSource 依赖性只更新到绑定对象上面去。
详细看:https://www.tutorialspoint.com/wpf/wpf_data_binding.htm
动态绑定到外部对象
对于双向绑定来说这个是必须的。
重写INotifyPropertyChanged接口
来区分下INotifyPropertyChanged和mode
如上,mode有三种模式不多讲了。
1、只重写INotifyPropertyChanged接口,确实能进行双向绑定。
2、只设置Mode = TwoWay也可以双向绑定。
但是它们有个区别。第二种情况,当数据更新时,它并不会立刻更新界面;要等界面再来取一次才行。第一种情况mode就默认了为TwoWay
所以mode和INotifyPropertyChanged配合才是最好的
Menu控件
这个控件可以像其他控件那样,随便放哪个地方,然后自己设置menu内容。Menu.Icon
设置单个选项的图标。InputGestureText
只是个显示内容,不会和指令绑定。Click
子项直接相应此属性的函数就好了。
Command
多说项:CanExecute返回false,会自动把控件设置为禁止状态。
先看下默认的,主要讲下:
Command,确实它能和指令绑定,但是默认只能和wpf能解析的指令绑定(自定义命令,下次再讲述吧)。
它设置命令后,如果想拦截命令的执行:
自定义command主要有俩种:
自定义
ICommand
1234567891011121314151617181920public class MyCommand : ICommand{public event EventHandler CanExecuteChanged{add { CommandManager.RequerySuggested += value; }remove { CommandManager.RequerySuggested -= value; }}public bool CanExecute(object parameter){return true;}public void Execute(object parameter){MessageBox.Show("www");}}调用时:要么:this.btn.Command = new MyCommand();或者<Button Command="{Binding MyCommand}要么:<local:MyCommand x:Key="ww" /> <Button Command="{StaticResource ww}" />这种`Command`信息比较少,适合默认执行类型。真要加信息也得加`CommandParameter`自定义
RoutedCommand
123456789101112131415161718192021222324252627282930313233public static RoutedCommand RMyCommand =new RoutedCommand("MYC", typeof(ForTest));public ForTest(){InitializeComponent();tc.Command = RMyCommand;CommandBinding comBind = new CommandBinding();comBind.Command = RMyCommand;comBind.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExecute);comBind.Executed += new ExecutedRoutedEventHandler(cb_Execute);gg.CommandBindings.Add(comBind);}private void cb_Execute(object sender, ExecutedRoutedEventArgs e){tb.Clear();e.Handled = true;}private void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e){if (string.IsNullOrEmpty(tb.Text)){e.CanExecute = false;}else{e.CanExecute = true;}e.Handled = true;}如上,用`RoutedCommand`新建一个(第三个参数是快捷键);大部分是多余的,和默认相比,中心思想就是新建一个command,添加到绑定。
渐变画刷
LinearGradientBrush
我在自定义控件界面时,想对背景色渐变。
这个是线性渐变,默认渐变线是对角线。
用startpoint endpoint来设置渐变线。
GradientStop 它表示渐变停止点,Offset来设置渐变线中百分比的偏移量(如:offset=”0.0” 这个点是从对角线左上开始的,有下个点它就停止在下个点的offset)
RadialGradientBrush
这个是个圆形的渐变。
渐变线就是圆的各个半径。
Center书面说它是圆的中心(这个指的是圆形状的中心),可以想象它是控制所有圆的宽窄,通过它来控制所有圆心
GradientOrigin渐变色开始位置(可以从圆边,和圆心)
RadiusX、RadiusY这俩个是半径
样式和模板
样式:http://www.wpf-tutorial.com/styles/using-styles/
分层、显隐式(x:Key; Style=”{StaticResource HeaderStyle}”)
//可以同一设置控件的属性内容
控件模板
模板:http://www.cnblogs.com/dingli/archive/2011/07/20/2112150.html
转换接口
对于静态绑定到内部对象太重要了,这个接口。
比如:通过输入no
,来禁止控件;一个是字符一个是bool,绑定就不会成功,所以需要转换。
|
|
动画
使用的结构也比较多,简单说下:
动画必须放入模板里面Storyboard
,这样一个模板可以包含多个动画可以同时触发。
触发方式有俩种:
1、放入EventTrigger进行触发,只是要多个BeginStoryboard
这样才能表示为此事件发生,模板开始触发。
2、放入Resources
内(这个时候只需要Storyboard
就够了)。因为有name属性,代码里面直接:name.Begin()
,模板开始触发。
自定义控件
custom control有点没看透,直接讲user control。
|
|
都是先注册静态变量创建,再编写属性设置。
依赖属性
wpf的控件是有共享的内存的,所以上面属性注册全用依赖属性注册。
官方说转换的时候 DependencyProperty.UnsetValue 会清空当前属性值。null 传给依赖属性是不行的,会被寻找其它值。
ControlTemplate和ContentTemplate
前者可以改变控件的外形。后者改变控件的内容。
比如你的button,想变成圆形,就用前者。你想Content="asasas"
这些内容圆形显示时就用后者。
由于强大的xaml,使的内容和形状都可以用控件表述。但是表述内容和DataTemplate联合无疑是好的选择: http://www.cnblogs.com/zhouhb/p/3284827.html
ZIndex
数字越小则层数越低,数字最大的在最前面
RenderTransform
|
|
1、RotateTransform:元素旋转:
Angle:旋转角度。
CenterX:旋转水平中心。
CenterY旋转的垂直中心}这两个是绝对定位坐标,
而RenderTransformOrigin是相对定位的
2、ScaleTransform:会对元素水平,垂直方向上缩放。
CenterX:缩放水平中心。CenterY缩放的垂直中心
ScaleX:水平缩放倍数 ScaleY:垂直缩放倍数。
3、SkewTransform:元素倾斜:
CenterX:倾斜水平中心。CenterY倾斜的垂直中心
AngleX:水平倾斜角度。AngleY:垂直倾斜角度。
4、TranslateTransform:元素移动(只对RenderTransform有效果)
X=水平移动像素,Y=垂直移动像素。
OpacityMask
简单形状的渐变直接fill渐变画刷就好了(而且画刷颜色直接指定透明度)。
可是路径和图片也要渐变的改变透明度只能用OpacityMask
Opacity
是指定控件的透明度
|
|
Dispatcher
在 WPF 中绝大部分控件都继承自 DispatcherObject,
甚至包括 Application。这些继承自 DispatcherObject 的对象具有线程关联特征,
也就意味着只有创建这些对象实例,且包含了 Dispatcher 的线程(通常指默认 UI 线程)才能直接对其进行更新操作