WPF快速精通版

命名空间:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:UserNamespace"       

WPF布局
1.Cavas画布:设置坐标值来布局,分别为Top, Left, Bottom., Right
如:Canvas.SetTop(控件名, 数值);

2.DockPanel面版:为其子控件提供相对的停靠位置, 包括向左停靠(Dock.Left),向右停靠(Dock.Right),向下停靠(Dock.Bottom),向上停靠(Dock.Up)
3.StackPanel面版:按照水平线方向或垂直线方向排列控件,按照指定的方向(HorizontalAlignment, VerticalAlignment)向其中添加子控件.
4.WrapPanel面版:自动换行子控件的布局,当子一行(或一列)不足以放置新控件时,WrapPanel将自动地将子控件放置到新行(或新列,这取决于Orientation属性)
5.Grid网格:Grid通过自定义行列来进行布局,这类似于表格.
6.UniGrid平均网格:Grid通过自定义行列来进行布局,每个格子大小一样。
7.ViewBox视图:可以自动缩放
8.ScrollViewer流动视图


WPF资源
1.资源通常用作“样式”(Style)、样式模板、数据模板等
1). 应用程序级资源:定义在App.xaml文件中,作为整个应用程序共享的资源
    <Application.Resources> 
 	 <SolidColorBrush Color="Red" x:Key="redBrush"></SolidColorBrush> 
    </Application.Resources> 

<Button Background="{StaticResource ResourceKey=redBrush}">使用应用程序集资源</Button>

2). 窗体资源:定义在Window或Page中,作为一个窗体或页面共享的资源存在 
 	    <Window.Resources> 
 	        <SolidColorBrush Color="Red" x:Key="redBrush"></SolidColorBrush> 
 	    </Window.Resources>

<Button Background="{StaticResource ResourceKey=redBrush}">使用应用窗体资源</Button> 

3). 文件资源:定义在资源字典的XAML文件中
 	    <Window.Resources> 
 	        <ResourceDictionary Source="Skin1.xaml"></ResourceDictionary> 
 	    </Window.Resources>
Button Background="{StaticResource ResourceKey=redBrush}">使用文件资源</Button> 

4).对象(控件)资源:定义在某个ContentControl中,作为其子容器、子控件共享的资源
	<StackPanel x:Name="stackPanel">
 	     <StackPanel x:Name="stackPanel"> 
 	        <StackPanel.Resources> 
 	            <ResourceDictionary Source="Skin1.xaml"></ResourceDictionary> 
 	        </StackPanel.Resources> 
	<Button Background="{StaticResource ResourceKey=redBrush}">使用应用控件资源</Button> 
	</StackPanel> 

2.资源文件解析的顺序
这个顺序和层叠样式表类似,优先级从高到底为:对象级,窗体级,应用程序集。静态资源(StaticResource)和动态资源(DynamicResource)

3.静态资源(StaticResource)和动态资源(DynamicResource) 
资源可以作为静态资源或动态资源进行引用。这是通过使用 StaticResource 标记扩展或 DynamicResource 标记扩展完成的。
通常来说,不需要在运行时更改的资源使用静态资源;而需要在运行时更改的资源使用动态资源。动态资源需要使用的系统开销大于静态资源的系统开销。 


4.使用mscorlib资源
1).window添加命名空间
xmlns:sys="clr-namespace:System;assembly=mscorlib"

2).添加资源
<Window.Resources>
     <sys:String x:Key="myString">
            string!!!!!
     </sys:String>

	<x:Array Type="sys:String" x:Key="myArray">
		<sys:String>数据1</sys:String>
		<sys:String>数据2</sys:String>
	</x:Array>
</Window.Resources>

3).使用资源
<TextBlock x:Name="txt2" Text="{Binding Source={StaticResource ResourceKey=myString}}" />

4).后台调用资源
string str=this.FindResource("myString") as string;

local资源
1).添加空间引用
xmlns:local="clr-namespace:UserNamespace"

2).定义后台程序
public class PathConverter:IValueConverter{}

3).定义local资源
<Window.Resources>
	<local:PathConverter x:Key="pc"></local:PathConverter>
</Window.Resources>

4).定义local资源
<Image Source="{Binding Name, Converter={StaticResource pc}}" />

5.可拓展标记资源
1).定义资源
    <Window.Resources>
        <SolidColorBrush x:Shared="false" x:Key="brush" Color="red" ></SolidColorBrush>
    </Window.Resources>

2).调用标记
<Button Content="Button" Background="{StaticResource ResourceKey=brush}"/>

3).后台编程
private void button1_Click(object sender, RoutedEventArgs e)
{
            SolidColorBrush scb = this.button2.Background as SolidColorBrush;
            scb.Color=Colors.Green;
}

WPF中的Style【只能改变控件的已有属性值】
Style是作为一种资源
<window.resources>
    <style targettype="Button" x:key="keyStyle">
        <Setter Property="Foreground" Value="Blue"/ > 
        ……
    </style>
    <Style TargetType="Button" BasedOn="{StaticResource keyStyle}">
      <Style.Triggers>
        <Trigger  Property="IsPressed" Value="True">>
        </Trigger>
      </Style.Triggers>
    </Style>
</window.resources>

TargetType="控件类型" 指示该Style的作用对象是控件类型
Setter设置器 Property="属性" Value="属性值"
x:key="key唯一名称" 调用方式:Style="{StaticResource key唯一名称}"
BasedOn="{StaticResource 继承另一个Style的key}"

后台编程
this.Button1.Style = (Style)FindResource("keyStyle");

WPF引用外部样式
实现方法: 
1.创建新建项添加/资源字典Style.xaml,并添加Style样式
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">   
    <Style x:Key="BaseStyle" TargetType="{x:Type Control}">   
        <Setter Property="Margin" Value="5" />   
    </Style>   
    <Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseStyle}">   
 
    </Style> 
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseStyle}">   
   
    </Style>
    ……
</ResourceDictionary>

2.引用外部资源,注意:在Window中添加外部样式需要指定key,而Application中则不需要
1).Window中添加外部样式
    <Window.Resources>   
        <ResourceDictionary x:Key="rdStyle">   
            <ResourceDictionary.MergedDictionaries>   
                <ResourceDictionary Source="Style.xaml" />   
            </ResourceDictionary.MergedDictionaries>   
        </ResourceDictionary>   
    </Window.Resources> 

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Style.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

3.将样式应用到窗口的布局上
<Grid Resources="{StaticResource rdStyle}">    
    ...    
</Grid>

WPF引用其他程序集中的样式
<Window.Resources >
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/ResourceLibrary;Component/Themes/Styles.xaml"></ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>


Style中的Trigger(触发器)【同样是样式,Trigger是预设的样式】
1).属性触发器Trigger,当与预设的属性值一致时,就会触发预设值的样式
 <Window.Resources>
    <Style TargetType="Button">
      <Style.Triggers>
        <Trigger  Property="IsPressed" Value="True">
          <Setter Property="Foreground" Value="Red"/>
        </Trigger>
      </Style.Triggers>
    </Style>    
  </Window.Resources>


注释:<Trigger  Property="IsPressed" Value="True">,当属性IsPressed为True时,就会触发Trigger预设的样式;

2).多属性触发器MultiTrigger
	<MultiTrigger> 
	<MultiTrigger.Conditions> 
		<Condition Property="属性一" Value="值一"></Condition> 
		<Condition Property="属性二" Value="值二"></Condition> 
	</MultiTrigger.Conditions> 
	</MultiTrigger> 
	<MultiTrigger.Setters> 
		//Style Setter
	</MultiTrigger.Setters> 

3).数据触发器DataTrigger
	<Style.Triggers> 
	<DataTrigger Binding="{Binding Path=Name}" Value="杨"> 
		<Setter Property="Foreground" Value="Red"></Setter> 
	</DataTrigger>                
	</Style.Triggers>
xaml页面
	<TextBox Text="{Binding Path=Name}"></TextBox> 
4.多条件数据触发器MultiDataTrigger
MultiDataTrigger这个类似MultiTrigger

5.事件触发器EventTrigger
<Style.Triggers>
	<EventTrigger RoutedEvent="MouseEnter"> 
		//Style Setter
	</EventTrigger> 
</Style.Triggers>

WPF中的ControlTemplate(控件模板)【由多个控件组合构成一个新的控件】
WPF包含数据模板和控件模板,其中控件模板又包括ControlTemplate和ItemsPanelTemplate
其实WPF的每一个控件都有一个默认的模板,该模板描述了控件的外观以及外观对外界刺激所做出的反应。我们可以自定义一个模板来替换掉控件的默认模板以便打造个性化的控件。

ControlTemplate包含两个重要的属性:
1,VisualTree,该模板的视觉树,其实我们就是使用这个属性来描述控件的外观的
2,Triggers,触发器列表,里面包含一些触发器Trigger,我们可以定制这个触发器列表来使控件对外界的刺激发生反应,比如鼠标经过时文本变成粗体等。

示例:画圆
	<Button Content="控件内容">
        <Button.Template>
          <ControlTemplate>
            <!--定义视觉树_start-->
            <Grid>
              <Ellipse Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}"  Fill="{TemplateBinding Button.Background}"/>
              <TextBlock Name="txtBlock" Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center"  HorizontalAlignment="Center"  Text="{TemplateBinding Button.Content}" />
            </Grid>
            <!--定义视觉树_end-->
            <!--定义触发器-->
            <ControlTemplate.Triggers>
              <Trigger  Property="Button.IsMouseOver"  Value="True">
                <Setter Property="Button.Foreground" Value="Red" />               
              </Trigger>
            </ControlTemplate.Triggers>
            <!--定义触发器_End-->
          </ControlTemplate>
        </Button.Template>
      </Button>


注释:
Width="{TemplateBinding Button.Width}",绑定控件的Width属性
<Button.Template>,模版定义
<ControlTemplate>,控件模版定义,里面是定义视觉树即排版

事件触发器(EventTrigger),触发预设的事件时调用的触发器

2).模版可以独立设置
  <Window.Resources>
    <ControlTemplate TargetType="Button" x:Key="ButtonTemplate">
        <!--定义视觉树-->
        <Grid>
          <Ellipse Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}"  Fill="{TemplateBinding Button.Background}"/>
          <TextBlock Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center"  HorizontalAlignment="Center"  Text="{TemplateBinding Button.Content}" />
        </Grid>
        <!--定义视觉树_end-->

	<!--定义控件资源-->
	<ControlTemplate.Resources>

	</ControlTemplate.Resources>
	<!--定义控件资源_end-->

        <!--定义触发器-->
        <ControlTemplate.Triggers>
          <Trigger  Property="Button.IsMouseOver"  Value="True">
            <Setter Property="Button.Foreground" Value="Red" />
          </Trigger>
        </ControlTemplate.Triggers>
        <!--定义触发器_End--> 
    </ControlTemplate>
  </Window.Resources>

调用模版:<Button Content="test btn" Template="{StaticResource ButtonTemplate}" />


3).数据模版【同样是模版只是绑定了数据DataType】【使用数据列表】
	第一步:定义数据
	namespace DataNameSpace
	{
		public class DataClass
		{
    			//数据List、Array、Model……
		}
	}

	第二步:XAML引用空间
	xmlns:data="clr-namespace:DataNameSpace" 

	第三步:调用类别
	<DataTemplate x:Key="DataT" DataType="{x:Type demo:DataClass}">

	第四步:调用数据
	Source="{Binding 数据}"

	第五步:调用模版
	ItemTemplate="{StaticResource  DataT}"

	第六步:指定数据源
	public MainWindow()
        {
            InitializeComponent();
            List<People> cars = new List<People>()
            {
                new People(){ name="杨家",age="10"},
                new People(){ name="李家",age="20"},
                new People(){ name="吴家",age="30"},
                new People(){ name="郭家",age="40"}
            };
            this.lbxControl.ItemsSource = cars;
        }


示例:设置个人信息
	第一步:定义数据对象
	namespace DataNameSpace
	{
    		public class DataClass
    		{
        		public string name { set; get; }
        		public string age { set; get; }
    		}
	}

	第二步:XAML引用空间
	xmlns:data="clr-namespace:DataNameSpace" 

	第三步:数据模版调用类别
    	<Window.Resources>
        <DataTemplate x:Key="DataT" DataType="{x:Type demo:DataClass}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding name}" Grid.Column="0" />
                <TextBlock Text="{Binding age}" Grid.Column="1" />
            </Grid>
        </DataTemplate>
    	</Window.Resources>

	第四步:调用数据
	Source="{Binding 数据}"

	第五步:控件调用模版
	<ListBox x:Name="lbxControl" ItemTemplate="{StaticResource  DataT}" />

	第六步:绑定数据源
	public MainWindow()
        {
            InitializeComponent();
            List<People> cars = new List<People>()
            {
                new People(){ name="杨家",age="10"},
                new People(){ name="李家",age="20"},
                new People(){ name="吴家",age="30"},
                new People(){ name="郭家",age="40"}
            };
            this.lbxControl.ItemsSource = cars;
        }


WPF转换器IValueConverter接口
    //转化为图片
    public class ImagesPathConverter:IValueConverter
    {
        
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string uriStr = string.Format(@"images/{0}.jpg",value.ToString());
            return new BitmapImage(new Uri(uriStr, UriKind.Relative));
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

HierarchicalDataTemplate分层数据模版
<HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding XPath=Student}">
	<CheckBox Content="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>


WPF绑定Binding【只是把一个对象属性值绑定在另一个对象的属性上】
1. DataContext共享源,子控件都可以调用父级资源【适用实体对象】
	第一步:定义数据对象
	namespace DataNameSpace
	{
    		public class DataClass
    		{
        		public string name { set; get; }
    		}
	}

	第二步:调用数据	
	<TextBox x:Name="txtName" Text="{Binding Path=name}"></TextBox> 

	第三步:绑定数据源
	this.txtName.DataContext = new People() { name = "microsoft-zn.cn" };

同样的方式:
<StackPanel x:Name="stackPanel">  
	<StackPanel.DataContext> 
		<local:Person Name="Jack" Age="30"></local:Person> 
	</StackPanel.DataContext>  
<StackPanel x:Name="stackPanel">  

2.双向绑定,实现更新控件UI(Invoke)
示例:
using System.ComponentModel;

public partial class MainWindow : Window
    {
        Micro ms;
        public MainWindow()
        {
            InitializeComponent();
            ms = new Micro() { name = "microsoft-zn.cn" };
            this.txtName.DataContext = ms;
        }

        private void txtNameChange_TextChanged(object sender, TextChangedEventArgs e)
        {
            //this.txtName.Text = this.txtNameChange.Text;
            ms.name = this.txtNameChange.Text; //双向绑定
        }
    }
    //对象Micro的name属性发生改变是,控件UI发生更新
    public class Micro : INotifyPropertyChanged
    {
        private string _name;
        public event PropertyChangedEventHandler PropertyChanged;
        public string name
        {
            get { return _name; }
            set
            {
                _name = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("name"));
                }
            }
        }
    }

3.Binding
1).Mode属性
oneWay:使用 OneWay 绑定时,每当源发生变化,数据就会从源流向目标。

OneTime: 绑定也会将数据从源发送到目标;但是,仅当启动了应用程序或 DataContext 发生更改时才会如此操作,因此,它不会侦听源中的更改通知。

OneWayToSource: 绑定会将数据从目标发送到源。

TwoWay: 绑定会将源数据发送到目标,但如果目标属性的值发生变化,则会将它们发回给源。

Default: binding的模式根据实际情况来定,如果是可编辑的就是TwoWay,只读的就是OneWay.

2).绑定到其它元素
<TextBox x:Name="textbox1" /> 
<Label Content="{Binding ElementName=textbox1, Path=Text}" /> 


3).绑定到静态资源
<Window.Resources> 
	<ContentControl x:Key="textContent">Hello, World!</ContentControl> 
</Window.Resources>
<Label x:Name="label1" Content="{Binding Source={StaticResource textContent}}" /> 

4).绑定到自身
<Label x:Name="label1" Content="{Binding RelativeSource={RelativeSource Self}, Path=Name}" /> 

5).绑定到指定类型的父元素
 	<Grid x:Name="Grid1"> 
 	        <StackPanel> 
 	            <Label x:Name="label1" Content="{Binding RelativeSource={RelativeSource FindAncestor,  
 	                AncestorType={x:Type Grid}}, Path=Name}" /> 
 	        </StackPanel> 
 	</Grid>

6)绑定到集合
 	public class Person  
 	    {  
 	        public string name { get; set; }  
 	    } 

	public class PersonList : ObservableCollection<Person>  {}

 	<Window.Resources>  
 	       <local:PersonList x:Key="person">  
 	           <local:Person name="杨"></local:Person>  
 	           <local:Person name="李"></local:Person>  
 	       </local:PersonList>  
 	   </Window.Resources>  

	<ListBox  ItemsSource="{Binding Source={StaticResource ResourceKey=person}}" DisplayMemberPath="name"></ListBox>               

7).使用XML作为Binding的源
xml文件
 	<?xml version="1.0" encoding="utf-8" ?>  
	<PersonList>  
	<Person id="1"><name>杨</name></Person>
	<Person id="2"><name>李</name></Person> 
	</PersonList>  

xaml页面
	<ListView x:Name="personListView">  
	<ListView.View>  
	<GridView>  
		<GridViewColumn Header="id" Width="100" DisplayMemberBinding="{Binding XPath=@id}"/>  
		<GridViewColumn Header="name" Width="100" DisplayMemberBinding="{Binding XPath=name}"/>  
	</GridView>  
	</ListView.View>  
	</ListView> 

后台代码
	XmlDocument xmlDocument = new XmlDocument();  
	xmlDocument.Load("Person.xml"); 
 	  
 	XmlDataProvider xdp = new XmlDataProvider();  
	xdp.Document = xmlDocument;  
	xdp.XPath = @"/PersonList/Person"; 
 	  
	this.personListView.DataContext = xdp;  
	this.personListView.SetBinding(ListView.ItemsSourceProperty, new Binding());  

7.后台代码设定Binding
1).准备Binding对象
Person p = new Person { age = 20, name = "Microsoft" }; 
Binding binding = new Binding();
binding.Source = p;
binding.Path = new PropertyPath("name");

2).用Binding对象将数据源和目标连结
假如在XAML处添加了一个TextBlock目标
<TextBlock x:Name="txtName"></TextBlock>

3).那么可以使用BindingOperations.SetBinding()方法将其进行binding了。
BindingOperations.SetBinding(txtName, TextBlock.TextProperty, binding);

4).也可以使用UI元素的基类FramworkElement封装的SetBinding函数
txtName.SetBinding(TextBlock.TextProperty, binding);

5).将上面两步结合在一起可以这样写
txtName.SetBinding(TextBlock.TextProperty, new Binding("Name") { Source=p});



WPF事件路由 
1).获取事件来源
xaml代码
<Grid x:Name="rootGrid" Button.Click="rootGrid_Click"> 
	<Button x:Name="btnOK" Margin="30">OK</Button> 
</Grid> 
</Window>

cs代码
private void rootGrid_Click(object sender, RoutedEventArgs e) 
{ 
	MessageBox.Show((e.Source as FrameworkElement).Name); //btnOk 
	MessageBox.Show((e.OriginalSource as FrameworkElement).Name); //btnOk 
}

WPF命令
WPF提供常用应用程序所用的命令集,常用的命令集包括:ApplicationCommands, ComponentCommands, NavigationCommands, MediaCommands和EditingCommands。
ApplicationCommands(应用程序命令):
CancelPrint:取消打印
Close:关闭
ContextMenu:上下文菜单
Copy:复制
CorrectionList: Gets the value that represents the Correction List command.
Cut:剪切
Delete:删除
Find:查找
Help:帮助
New:新建
NotACommand:不是命令,被忽略
Open:打开
Paste:粘贴
Print:打印
PrintPreview:打印预览
Properties:属性
Redo:重做
Replace:取代
Save:保存
SaveAs:另存为
SelectAll:选择所有的
Stop:停止
Undo:撤消 

示例:

xaml文件
<Window.CommandBindings> 
	<CommandBinding Command="cmd" CanExecute="Command_CanExecute" Executed="Command_CanExecuted"></CommandBinding> 
</Window.CommandBindings> 

<Button x:Name="btnWPF" Margin="10" Command="cmd" CommandParameter="WPF">新建WPF</Button> 

cs文件
private void Command_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
{
	e.CanExecute = string.IsNullOrEmpty(textBox.Text); 
 } 

private void Command_Executed(object sender, ExecutedRoutedEventArgs e) 
{
	//执行命令
	if (e.Parameter.ToString() == "Library") {}
}

 

你可能感兴趣的:(WPF快速精通版)