WPF深入浅出代码案例

画一个椭圆

<Window x:Class="WpfApp3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Ellipse Name="rectangle"  Width="90" Height="90">
            <Ellipse.Fill>
                <RadialGradientBrush GradientOrigin="0.25,0.25" RadiusX="0.75" RadiusY="0.75">
                    <RadialGradientBrush.GradientStops>
                        <GradientStop Color="White" Offset="0"/>
                        <GradientStop Color="Black" Offset="0.65"/>
                        <GradientStop Color="Gray" Offset="0.8"/>
                    </RadialGradientBrush.GradientStops>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
    </Grid>
</Window>
xaml

GradientOrigin:定义渐变开始的二维焦点的位置。

RadiusX:径向渐变的最外面圆的水平半径。

RadiusY:径向渐变的最外面圆的垂直半径。

GradientStop:渐变中转换点的位置和颜色。

 ------------------------------------------------------------------------------------------

标记扩展

        <Slider Name="slider" HorizontalAlignment="Left" Margin="92,203,0,0" VerticalAlignment="Top" Width="205"/>
        <TextBlock Text="{Binding ElementName=slider,Path=Value ,Mode=OneWay}" Margin="96,259,244,132"></TextBlock>

------------------------------------------------------------------------------------------

4.x:名称空间

x:key

为了在XAML中使用string类,需要

xmlns:sys="clr-namespace:System;assembly=mscorlib"

在XAML调用时,

<TextBox Text="{StaticResource ResourceKey=my}"        Margin="255,314,0,0"   VerticalAlignment="Top" Width="120"/>

在c#中调用

            string str = this.FindResource("my") as string;
            this.textbox1.Text = str;

------------------------------------------------------------------------------------------

x:type  案例代码一直提示未找到MyButton   

打开工程属性------生成------目标平台:如果原来是Any CPU,则切换为x86或x64,保存!然后清理解决方案!重新生成解决方案!

------------------------------------------------------------------------------------------

x:null

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
            <Setter Property="Width" Value="60"/>
            <Setter Property="Height" Value="36"/>
            <Setter Property="Margin" Value="5"/>
        </Style>
        
    </Window.Resources>
    <StackPanel Background="LightSlateGray">
        <Button  Content="ok"/>
        <Button  Content="ok"/>
        <Button  Content="ok"/>
        <Button  Content="ok" Style="{x:Null}"/>
    </StackPanel>
</Window>
View Code

x:array

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel Background="LightSlateGray">
        <ListBox>
            <ListBox.ItemsSource>
                <x:Array Type="sys:String">
                    <sys:String>tom</sys:String>
                    <sys:String>jack</sys:String>
                    <sys:String>tony</sys:String>
                </x:Array>
            </ListBox.ItemsSource>
        </ListBox>
    </StackPanel>
</Window>
View Code

x:static

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="{x:Static local:MainWindow.WindowsTitle}" Height="450" Width="800">
    
    <StackPanel Background="LightSlateGray">
        <TextBox Text="{x:Static local:MainWindow.ShowText}"/>
    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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 WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public static string WindowsTitle = "啊哈哈哈哈";
        public static string ShowText { get { return "abandon"; } }

        public MainWindow()
        {
            InitializeComponent();
        }
       
    }
}
cs

5.控件与布局

6.深入浅出话binding

让binding源的对象具有自动通知binding 自己属性值已变化

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <StackPanel>
        <TextBlock x:Name="textblockname"></TextBlock>
        <Button Height="50" Click="Button_Click"></Button>
    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        Student stu = new Student();
        public MainWindow()
        {
            InitializeComponent();

           
            Binding userbinding = new Binding();
            userbinding.Source = stu;
            userbinding.Path = new PropertyPath("Name");
            //使用binding绑定数据源和binding目标

            BindingOperations.SetBinding(this.textblockname, TextBlock.TextProperty, userbinding);//绑定的绑定目标 绑定的目标属性 描述绑定的BindingBase对象
        }



        class Student : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private string name;
            public string Name
            {
                get { return name; }
                set 
                {
                    name = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                    }
                }                
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            stu.Name += "1";
        }
    }
}
cs

 

显式的为数据设置DataTemplate

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <StackPanel>
 
        
         <TextBox x:Name="textBox1" Text="{Binding Path=Id}"  BorderBrush="Aqua" Margin="5"></TextBox>
        <ListBox x:Name="listbox1" Height="100" Margin="5">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Id}" Background="Pink" Width="30"/>
                        <TextBlock Text="{Binding Path=Name}" Background="Blue"  Width="50"/>
                        <TextBlock Text="{Binding Path=Age}" Background="Red" Width="80"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
       
    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {

            InitializeComponent();

            List<Studetn1> stulist = new List<Studetn1>()
            {
                new Studetn1(){ Id=0,Name="tim",Age=29 },
                new Studetn1(){ Id=2,Name="tom",Age=22 },
                new Studetn1(){ Id=3,Name="vina",Age=230 },
                new Studetn1(){ Id=4,Name="mike",Age=20 },

            };

            this.listbox1.ItemsSource = stulist;
            //this.listbox1.DisplayMemberPath = "Name";


            this.textBox1.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = this.listbox1 });

        }
        
        public class Studetn1
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }

        }



    }
}
cs

在使用集合类型作为列表控件的ItemsSource时一般会考虑使用ObservableCollection<T>代替List<T>,因为ObservableCollection<T>类实现了INotifyCollectionChange和INotifyPropertyChange接口,能把集合的变化立刻通知他的列表控件。

6.3.8  使用ADO.NET对象作为Binding的源  后面看实例

6.3.9  使用XML数据作为Binding的源

.NET Framework提供了两套处理XML数据的类库

符合DOM(Document Object Model 文档对象模型)

以LINQ(Language-Intergrated Query 语言集成查询)

注意:当使用XML数据作为Binding的Source时我们将使用XPath 属性而不是Path属性来指定对象。

基于DOM标准的XML类库使用

如何建立XML文件

 XML文件内容如下

<?xml version="1.0" encoding="utf-8"?>
<StudentList>
    <Student Id="1">
        <Name>Time1</Name>
    </Student>
    <Student Id="2">
        <Name>Time2</Name>
    </Student>
    <Student Id="3">
        <Name>Time3</Name>
    </Student>
    <Student Id="4">
        <Name>Time4</Name>
    </Student>
</StudentList>
XML
Xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }
       
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(@"D:\suwen\Desktop\XMLFile1.xml");
            XmlDataProvider xdp = new XmlDataProvider();
            xdp.Document = doc;
            //使用Xpath选择需要暴露的数据
            //现在时需要暴露一组Student
            xdp.XPath = @"StudentList/Student";
            this.listViewStudents.DataContext = xdp;
            this.listViewStudents.SetBinding(ListView.ItemsSourceProperty, new Binding());
        }
    }
}
cs

使用LINQ检索结果作为Binding的源

在Button被单击的时候显示一个Students集合类型对象

从一个已经填充好的List<Student>对象中检索出所有名字以之母T开头的学生,代码如下

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <StackPanel Background="AliceBlue">
        <ListView x:Name="listViewStudents" Height="130" Margin="5">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Id" Width="80"
                                    DisplayMemberBinding="{Binding Id}"/>
                    <GridViewColumn Header="Name" Width="120"
                                    DisplayMemberBinding="{Binding Name}"/>
                    <GridViewColumn Header="Age" Width="120"
                                    DisplayMemberBinding="{Binding Age}"/>
                </GridView>
            </ListView.View>
        </ListView>
        <Button Content="load" Click="Button_Click_2"/>
    </StackPanel>
</Window>
Xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }
        public class Student
        {
            public int Id { get; set;  }
            public string Name { get; set; }
            public int Age { get; set; }
        }
       
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {

            List<Student> stulist = new List<Student>()
            {
                new Student(){ Id=0,Name="Tim",Age=20},
                new Student(){ Id=1,Name="T5im",Age=21},

            };
            this.listViewStudents.ItemsSource = from stu in stulist where stu.Name.StartsWith("T") select stu;
                
        }
    }
}
cs

6.3.11  使用ObjectDataProvider对象作为Binding的Source

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <StackPanel Background="AliceBlue">
       
        <Button Content="load" Click="Button_Click_2"/>
    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }
        public class Calculator
        {
            public string Add(string arg1, string arg2)
            {
                double x = 0;
                double y = 0;
                double z = 0;
                if (double.TryParse(arg1, out x) && double.TryParse(arg2, out y))
                {
                    z = x + y;
                    return z.ToString();
                }
                return "input Error";
            }
        

        }
       
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {

            ObjectDataProvider odp = new ObjectDataProvider();
            odp.ObjectInstance = new Calculator();
            odp.MethodName = "Add";
            odp.MethodParameters.Add("100");
            odp.MethodParameters.Add("300");
            MessageBox.Show(odp.Data.ToString());
        }
    }
}
cs

6.3.11  使用Bingding的RelativeSource

不确定作为Source的对象叫什么名字,但知道它作为Binding目标的对象在UI布局上有相对关系。

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <Grid x:Name="grid1" HorizontalAlignment="Left" Height="178" Margin="65,63,0,0" VerticalAlignment="Top" Width="532">
        <DockPanel x:Name="dockPanel1" HorizontalAlignment="Left" Height="140" LastChildFill="False" Margin="84,44,0,-6" VerticalAlignment="Top" Width="369">
            <StackPanel x:Name="stackPanel1" Height="140" VerticalAlignment="Top" Width="254">
                <Grid x:Name="grid2" Height="100">
                    <Grid x:Name="grid3" Height="100">
                        <TextBlock x:Name="textBlock1" HorizontalAlignment="Left" Margin="103,46,0,0" TextWrapping="Wrap" VerticalAlignment="Top"><Run Text="TextBlock"/></TextBlock>
                    </Grid>
                    
                </Grid>
            </StackPanel>
        </DockPanel>
    </Grid>

</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            RelativeSource rs = new RelativeSource(RelativeSourceMode.FindAncestor);

            rs.AncestorLevel = 2;//以Binding目标控件为起点的层级偏移量
            rs.AncestorType = typeof(Grid);//告诉Binding寻找哪个类型的对象那个作为自己的源,不是这个类型的对象会被跳过
            Binding binding = new Binding("Name") { RelativeSource = rs };
            this.textBlock1.SetBinding(TextBlock.TextProperty, binding);
        }   

    }
}
cs

6.4  Binding对数据的转化与校验

6.4.1  binding的数据校验

Binding用于数据有效性校验的关卡是它的ValidationRules

textbox 显示slider的数据,如果数据校验失败显示错误

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <Grid x:Name="grid1" HorizontalAlignment="Left" Height="178" Margin="65,63,0,0" VerticalAlignment="Top" Width="532">
        <TextBox x:Name="TextBox1" HorizontalAlignment="Left" Height="23" Margin="189,113,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
        <Slider x:Name="Slider1" Minimum="0" Maximum="110" HorizontalAlignment="Left" Margin="100,59,0,0" VerticalAlignment="Top" Width="327"/>

    </Grid>

</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

            Binding binding = new Binding("Value") { Source = this.Slider1 };
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            RangeValidationRule rvr = new RangeValidationRule();
            rvr.ValidatesOnTargetUpdated = true;

            binding.ValidationRules.Add(rvr);
            binding.NotifyOnValidationError = true;
            this.TextBox1.SetBinding(TextBox.TextProperty, binding);

            this.TextBox1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));
        }

        //需要一个ValidationRule的派生类
        public class RangeValidationRule : ValidationRule
        {
            //实现Validate方法
            public override ValidationResult Validate(object value, CultureInfo cultureInfo)
            {
                double d = 0;
                if (double.TryParse(value.ToString(), out d))
                {
                    if (d >= 0 && d <= 100)
                    {
                        return new ValidationResult(true, null);
                    }
                }
                return new ValidationResult(false, "Validation Failed");
            }

        }

        //用于侦听校验错误事件的事件处理器如下:
        void ValidationError(object sender, RoutedEventArgs e)
        {
            if (Validation.GetErrors(this.TextBox1).Count > 0)
            {
                this.TextBox1.ToolTip = Validation.GetErrors(this.TextBox1)[0].ErrorContent.ToString();
            }
        }

    }
}
cs

6.4.2  binding的数据转化

涉及,飞机的category单向转换为string(XAML编译器能把string对象解析为图片资源),state与bool?类型之间的双向转化

按下load在listbox显示飞机的类别,名称,状态,,按下save可以将信息保存在txt文件内容。

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <Window.Resources>
        <local:CategoryToSourceConventer x:Key="cts"/>
        <local:StateToNullableBollConventer x:Key="stnb"/>
    </Window.Resources>

    <StackPanel Background="LightBlue">
        <ListBox x:Name="listBoxPlane" Height="160" Margin="5">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Width="20" Height="20"  
                               Source="{Binding Path=Category,Converter={StaticResource cts}}"/>

                        <TextBlock Text="{Binding Path=Name}" Width="60" Margin="80,0"/>
                        <CheckBox IsThreeState="True"
                                       IsChecked="{Binding Path=State,Converter={StaticResource stnb}}"/>
                               
                    </StackPanel>
                </DataTemplate>
                
            </ListBox.ItemTemplate>
            
        </ListBox>
        <Button x:Name="buttonLoad" Content="Load" Height=" 25" Margin="5,0" Click="buttonLoad_Click"/>
        <Button x:Name="buttonSave" Content="Save" Height=" 25" Margin="5,5" Click="buttonSave_Click"/>

    </StackPanel>

</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void buttonLoad_Click(object sender, RoutedEventArgs e)
        {
            List<Plane> palneList = new List<Plane>()
            {
            new Plane(){ Category=Category.Bomber,Name="B-1",State=State.Unknown},
            new Plane(){ Category=Category.Bomber,Name="B-2",State=State.Unknown},
            new Plane(){ Category=Category.Fighter,Name="F-22",State=State.Unknown},
            new Plane(){ Category=Category.Fighter,Name="Su-47",State=State.Unknown},
            new Plane(){ Category=Category.Bomber,Name="B-52",State=State.Unknown},
            new Plane(){ Category=Category.Fighter,Name="J-10",State=State.Unknown},
            };
            this.listBoxPlane.ItemsSource = palneList;

        }

        private void buttonSave_Click(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Plane p in listBoxPlane.Items)
            {
                sb.AppendLine(string.Format("Catedory={0} Name={1},State={2}", p.Category, p.Name, p.State));
            }
            File.WriteAllText(@"D:\PlaneList.txt", sb.ToString());
        }
    }


    //轰炸机的类别,轰炸机的状态,飞机
    public enum Category
    {
        Bomber,
        Fighter
    }
    public enum State
    {
        Available,
        Locked,
        Unknown
    }

    public class Plane
    {
        public Category Category { get; set; }
        public string Name { get; set; }
        public State State { get; set; }

    }

    public class CategoryToSourceConventer : IValueConverter
    {
        //将Category转换为Uri
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Category c = (Category)value;
            switch (c)
            {
                case Category.Bomber:
                    return @"\Icon\Bomber.png";
                case Category.Fighter:
                    return @"\Icon\Fighter.png";
                default:
                    return null;
            }
        }
        //不会被调用
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class StateToNullableBollConventer : IValueConverter
    {
        //将State转换为boll?
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            State s = (State)value;
            switch (s)
            {
                case State.Locked:
                    return false;
                case State.Available:
                    return true;
                case State.Unknown:
                default:
                    return null;
            }
        }
        //boll?转换为State
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool? nb = (bool?)value;
            switch (nb)
            {
                case true:
                    return State.Available;
                case false:
                    return State.Locked;
                case null:
                default:
                    return State.Unknown;
            }
        }
    }
}
cs

6.5  MultiBinding(多路Binding)

 UI需要显示的信息由不止一个数据源来决定,需要使用MultBinding

需求:有一个用于新用户注册的UI(包含4个TextBox和1个Button)还有如下一些限定

第一,第二TextBox输入用户名,要求内容一致

第三,第四TextBox输入用户E-Mail,要求内容一致。

当TextBox全部输入一致时,Button可用

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <StackPanel Background="Lavender">
        <TextBox x:Name="textBox1" Height="23" Margin="5"></TextBox>
        <TextBox x:Name="textBox2" Height="23" Margin="5,0"></TextBox>
        <TextBox x:Name="textBox3" Height="23" Margin="5"></TextBox>
        <TextBox x:Name="textBox4" Height="23" Margin="5,0"></TextBox>
        <Button x:Name="button1" Content="Submit" Width="80" Margin="5"/>

    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            this.SetMultiBinding();

        }
        private void SetMultiBinding()
        {
                Binding b1 = new Binding("Text") { Source = this.textBox1 };
                Binding b2 = new Binding("Text") { Source = this.textBox2 };
                Binding b3 = new Binding("Text") { Source = this.textBox3 };
                Binding b4 = new Binding("Text") { Source = this.textBox4 };

            MultiBinding mb = new MultiBinding() { Mode = BindingMode.OneWay };
            mb.Bindings.Add(b1);
            mb.Bindings.Add(b2);
            mb.Bindings.Add(b3);
            mb.Bindings.Add(b4);

            mb.Converter = new LogonMultiBindingConvert();

            this.button1.SetBinding(Button.IsEnabledProperty, mb);
        }

        public class LogonMultiBindingConvert : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                if (!values.Cast<string>().Any(text=>string.IsNullOrEmpty(text))
                
                    && values[0].ToString() == values[1].ToString()
                    && values[2].ToString() == values[3].ToString())
                {
                    return true;
                }
                return false;
            }

            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }

           
        }



    }
}


   
cs

7.深入浅出话属性

7.22  声明和使用依赖属性

两个TextBox,按下button后,第二个TextBox显示第一个TextBox的内容

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="123" Height="450" Width="800">
    <StackPanel Background="Lavender">
        <TextBox x:Name="textBox1" Height="23" Margin="5"></TextBox>
        <TextBox x:Name="textBox2" Height="23" Margin="5,0"></TextBox>
        <Button x:Name="button1" Content="dependency" Width="80" Margin="5" Click="button1_Click"/>

    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            

        }

        public class Student : DependencyObject
        {
            public static readonly DependencyProperty NameProperty =
                    DependencyProperty.Register("Name", typeof(string), typeof(Student));
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Student stu = new Student();
            stu.SetValue(Student.NameProperty, this.textBox1.Text);
            textBox2.Text = (string)stu.GetValue(Student.NameProperty);
        }
    }
}


   
cs

提示:在一个类中声明依赖属性时,并不需要手动声明、注册并使用CLR属性封装,只需要输入propdp,,Visual Studio 提示列表中会有一项高亮显示,此时连续按下两下Tab键,,一个标准的依赖属性就声明好了。

8.深入浅出话事件

8.3.3  自定义路由事件

 在ListBox显示路由事件发生时间

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="Route Event"
        mc:Ignorable="d"
        x:Name="window_1"  Height="450" Width="800"
         local:TimeButton.ReportTime="ReportTimeHandler"
        >
    <Grid x:Name="grid_1"  local:TimeButton.ReportTime="ReportTimeHandler">
        <Grid x:Name="grid_2"   local:TimeButton.ReportTime="ReportTimeHandler">
            <Grid x:Name="grid_3"   local:TimeButton.ReportTime="ReportTimeHandler">
                <StackPanel x:Name="stackPanel_1"  local:TimeButton.ReportTime="ReportTimeHandler"
                    >
                    <ListBox x:Name="listBox"   local:TimeButton.ReportTime="ReportTimeHandler"/>
                    <local:TimeButton x:Name="timeButton" Width="80" Height="80" 
                    Content="报时"  local:TimeButton.ReportTime="ReportTimeHandler"/>
                    
                </StackPanel>




            </Grid>
        </Grid>
    </Grid>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();


        }
        private void ReportTimeHandler(object sender, ReporTimeEventArgs e)
        {
            FrameworkElement element = sender as FrameworkElement;
            string timeStr = e.ClickTime.ToLongTimeString();
            string contnet = string.Format("{0}到达{1}", timeStr, element.Name);
            this.listBox.Items.Add(contnet);


        }


    }
    //用于承载时间消息的事件参数
    class ReporTimeEventArgs : System.Windows.RoutedEventArgs
    {
        public ReporTimeEventArgs(RoutedEvent routedEvent, object source)
            : base(routedEvent, source) { }
        public DateTime ClickTime { get; set; }
    }

    class TimeButton : Button
    {
        //声明和注册路由事件
        public static readonly RoutedEvent ReporTimeEvent = EventManager.RegisterRoutedEvent
            ("ReportTime", RoutingStrategy.Bubble, typeof(EventHandler<ReporTimeEventArgs>), typeof(TimeButton));

        //CLR事件包装器
        public event RoutedEventHandler ReportTime
        {
            add { this.AddHandler(ReporTimeEvent, value); }
            remove { this.RemoveHandler(ReporTimeEvent, value); }


        }

        //激发路由事件,借用Click事件的激发方法
        protected override void OnClick()
        {
            base.OnClick();//保证Button原有功能正常使用

            ReporTimeEventArgs args = new ReporTimeEventArgs(ReporTimeEvent, this);
            args.ClickTime = DateTime.Now;
            this.RaiseEvent(args);

        }
        //ReportTimeEvent路由事件处理器
    }


}
cs

8.3.3  RoutedEventArgs的Source与OriginalSource

VisualTree与LogicalTree区别就在于LogicalTree的叶子结点是构成用户界面的控件,而VisualTree要连控件中的细微结构也算上。

RoutedEventArgs两个属性,Source表示Logical上的消息源头,OriginalSource表示VisualTree上的源头

 8.3.4  事件也附加-深入浅出附加事件

附加事件的宿主没有界面渲染功能,但是是可以使用附加事件与其他对象进行沟通。

设计一个名为Student的类,如果Student实例Name属性值发生的变化就激发一个路由事件,使用界面元素来捕捉这个事件。

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        mc:Ignorable="d"
        x:Name="window_1"  Height="450" Width="800">
    <Grid x:Name="gridMain">
        <Button x:Name="button1" Content="OK" Width="80" Height="80" Click="button1_Click">
            
        </Button>
        
    </Grid>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

            //为外层Grid添加路由事件侦听器
            Student.AddNameChangedHandler(
                this.gridMain,
                new RoutedEventHandler(this.StudentNameChangedHandler));


                

        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Student stu = new Student { ID = 10, Name = "Tim" };
            stu.Name = "Tom";
            //准备事件消息并发送路由事件
            RoutedEventArgs arg = new RoutedEventArgs(Student.NameChangedEvent, stu);
            this.button1.RaiseEvent(arg);
        }
        //Grid捕捉到NameChangedEvent后的处理器
        private void StudentNameChangedHandler(object sender, RoutedEventArgs e)
        {
            MessageBox.Show((e.OriginalSource as Student).ID.ToString());
        }
    }


    public class Student
    {
        //声明定义路由事件
        public static readonly RoutedEvent NameChangedEvent = EventManager.RegisterRoutedEvent
                ("NameChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Student));

        //为界面元素添加路由事件侦听
        public static void AddNameChangedHandler(DependencyObject d, RoutedEventHandler h)
        {
            UIElement e = d as UIElement;
            if (e != null)
            {
                e.AddHandler(Student.NameChangedEvent, h);
            }
        }
        //移除侦听
        public static void RemoveNameChangedHandler(DependencyObject d, RoutedEventHandler h)
        {
            UIElement e = d as UIElement;
            if (e != null)
            {
                e.RemoveHandler(Student.NameChangedEvent, h);
            }
        }
        public int ID { get; set; }
        public string Name { get; set; }
    }
}
cs

9  深入浅出话命令

9.1  命令系统的基本元素与关系

9.1.1  命令系统的基本元素

WPF的命令系统由几个基本要素构成

命令(Comamand)实际上就是实现了ICommad接口的类

命令源(CommandSource)即命令的发送者,是实现了IcommandSource接口的类

命令目标(CommandTarget)命令将发送给谁,命令目标必须是实现了IInputElement接口的类

命令关联(CommandBinding)负责把一些外围逻辑与命令关联起来

9.1.2  基本元素之间的关系

基本元素之间的关系体现在使用命令的过程中。命令使用大概分为如下几步:

(1)创建命令类:及获得一个实现Icommand接口的类,

(2)声明命令实例

(3)指定命令的源

(4)指定命令目标

(5)设置命令关联

9.1.3  小试命令

需求:定义一个命令,使用Button来发送这个命令,当命令送达TextBox时,TextBox会被清空(如果TextBox中没有文字则命令不可以被发送)

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        mc:Ignorable="d"
        x:Name="window_1"  Height="450" Width="800">
    <StackPanel x:Name="stackPanel">
        <Button x:Name="button1" Content="send Command" Margin="5"  />
        <TextBox x:Name="textBoxA" Margin="5" Height="100" />
    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            InitializeCommand();
                

        }

        //声明并定义命令
        private RoutedCommand clearCmd = new RoutedCommand("Clear", typeof(MainWindow));

        private void InitializeCommand()
        {
            //把命令赋值给命令源(发送者)并指定快捷键
            this.button1.Command = this.clearCmd;
            this.clearCmd.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));
            //指定命令目标
            this.button1.CommandTarget = this.textBoxA;
            //创建命令关联
            CommandBinding cb = new CommandBinding();
            cb.Command = this.clearCmd;         //只关注与clearCmd相关的事件
                cb.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExecute);
            cb.Executed += new ExecutedRoutedEventHandler(cb_Executed);

            //把命令关联安置在外围控件上
            this.stackPanel.CommandBindings.Add(cb);                 
        }
        //当探测命令是否可以执行是,此方法被调用
        void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(this.textBoxA.Text))
            {
                e.CanExecute = false;
            }
            else
            {
                e.Handled = true;
            }
            //避免继续向上传而降低程序性能
            e.Handled = true;
        }
        //当命令到达后,命令被调用
        void cb_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.textBoxA.Clear();
            //避免继续向上传而降低程序性能
            e.Handled = true;
        }


    }


    
}
cs

因为CanExecute事件的激发频率比较高,为避免降低性能处理完后,建议把e.Handled设为true

CommandBinding一定哟啊设置在命令目标的外围控件上,不然呢无法捕捉到CanExecute和Executed等路由事件。

9.1.4  WPF的命令库

WPF准备了一些便捷的命令库

ApplicationCommands

ComponentCommands

NavigationCommands

MediaCommands

EditingCommans

9.1.5  命令参数

运行程序,当TextBox中没有内容时,两个按钮均不可用;当输入文字后,按钮变可用,单击按钮,LIstBox会加入不同条目

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        mc:Ignorable="d"
        x:Name="window_1"  Height="450" Width="800">
    <Grid Margin="6">
        <Grid.RowDefinitions>
            <RowDefinition Height="24"/>
            <RowDefinition Height="4"/>
            <RowDefinition Height="24"/>
            <RowDefinition Height="4"/>
            <RowDefinition Height="24"/>
            <RowDefinition Height="4"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <!--命令和命令参数 -->
        <TextBlock Text="Name:" VerticalAlignment="Center" HorizontalAlignment="Left"
                Grid.Row="0"/>
        <TextBox x:Name="nameTextBox" Margin="60,0,0,0"  
                Grid.Row="0"/>
        <Button Content="New Teacher" Command="New"  CommandParameter="Teacher"
                Grid.Row="2"/>
        <Button Content="New Teacher" Command="New"  CommandParameter="Teacher"
                Grid.Row="2"/>
        <Button Content="New Student" Command="New"  CommandParameter="Student"
                Grid.Row="4"/>
        <ListBox x:Name="listBoxNewItems" Grid.Row="6"/>
    </Grid>
    <!--为窗体添加CommandBinding-->
    <Window.CommandBindings>
        <CommandBinding Command="New" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed"/>
    </Window.CommandBindings>
    
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            
                

        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(this.nameTextBox.Text))
            {
                e.CanExecute = false;

            }
            else
            {
                e.CanExecute = true;
            }
        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            string name = this.nameTextBox.Text;
            if (e.Parameter.ToString()=="Teacher")
            {
                this.listBoxNewItems.Items.Add(string.Format("New Teacher:{0},学而不厌,诲人不倦。", name));
            }
            if (e.Parameter.ToString() == "Student")
            {
                this.listBoxNewItems.Items.Add(string.Format("New Teacher:{0},好好学习,天天向上。", name));
            }
        }
    }


    
}
cs

9.1.6  命令与Binding的结合

9.2  近观命令

9.2.1  ICommand接口与RoutedCommand

9.2.2  自定义Command

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        mc:Ignorable="d"
        x:Name="window_1"  Height="450" Width="800">
    <StackPanel>
        <local:MyCommandSource x:Name="ctrlClear" Margin="10">
            <TextBlock Text="清除" FontSize="16" TextAlignment="Center" Background="LightBlue" Width="80" />
        </local:MyCommandSource>
        <local:MiniView x:Name="miniView"/>
    </StackPanel>
</Window>
mainWindow.xaml
<UserControl x:Class="WpfApp4.MiniView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp4"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Border CornerRadius="5" BorderBrush="LawnGreen" BorderThickness="5">
        <StackPanel>
            <TextBox x:Name="textBox1" Margin="5" />
            <TextBox x:Name="textBox2" Margin="5,0" />
            <TextBox x:Name="textBox3" Margin="5" />
            <TextBox x:Name="textBox4" Margin="5,0" />
        </StackPanel>
    </Border>
</UserControl>
miniWindow.xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

            //声明命令并使用命令源和目标与之关联
            ClearCommand clearCmd = new ClearCommand();
            this.ctrlClear.Command = clearCmd;
            this.ctrlClear.CommandTarget = this.miniView;

        }

    }

    public interface IView
    { 
        //属性
        bool isChanged { get; set; }
        //方法
        void SetBinding();
        void Refresh();
        void Clear();
        void Save();
    }
    //自定义命令
    public class ClearCommand : ICommand
    {
        //当命令可执行状态发生变化时,应被激发
        public event EventHandler CanExecuteChanged;
        //用于判断命令是否可以执行(暂不实现)
        public bool CanExecute(object parament)
        {
            throw new NotImplementedException();
        }

        //命令执行带有业务相关的Clear逻辑
        public void Execute(object parameter)
        {
            IView view = parameter as IView;
            if (view!=null)
            {
                view.Clear();
            }
        }
    }

    //自定义命令源
    public class MyCommandSource : UserControl, ICommandSource
    { 
        //继承自ICommandSource的三个属性
        public ICommand Command { get; set; }
        public object CommandParameter { get; set; }
        public IInputElement CommandTarget { get; set; }

        //在组件被单击时连带执行命令
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            //在命令目标上执行命令,或称让命令作用于命令目标
            if (this.CommandTarget!=null)
            {
                this.Command.Execute(this.CommandTarget);
            }
        }
    }



    
}
mainWindow.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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 WpfApp4
{
    /// <summary>
    /// MiniView.xaml 的交互逻辑
    /// </summary>
    public partial class MiniView : UserControl,IView
    {
        public MiniView()
        {
            InitializeComponent();
        }

        //继承自IView的成员们
        public bool isChanged { get ; set; }

        public void SetBinding() { }
        public void Refresh() { }
        public void Save() { }
        //用于清除内容的业务逻辑
        public void Clear()
        {
            this.textBox1.Clear();
            this.textBox2.Clear();
            this.textBox3.Clear();
            this.textBox4.Clear();
        }
       
    }
}
miniWindow.cs

10  深入浅出话资源

10.2  且”静“且“动”的资源

DynamicResource:动态资源使用

StaticResource:静态资源使用

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        mc:Ignorable="d"
        x:Name="window_1"  Height="450" Width="800">
    <Window.Resources>
        <TextBlock x:Key="res1" Text="海上生明月"/>
        <TextBlock x:Key="res2" Text="海上生明月"/>
    </Window.Resources>
    <StackPanel>
        <Button Margin="5,5,5,0" Content="{StaticResource res1}"/>
        <Button Margin="5,5,5,0" Content="{DynamicResource res2}"/>
        <Button Margin="5,5,5,0" Content="Update" Click="Button_Click"/>
    </StackPanel>
    
    
    
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

            //声明命令并使用命令源和目标与之关联
         
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Resources["res1"] = new TextBlock() { Text = "天涯共此时" };
            this.Resources["res2"] = new TextBlock() { Text = "天涯共此时" };
        }
    }

   



    
}
cs

10.3  向程序添加二进制资源

注意:如果想让外部文件编译进目标成为二进制资源,必须在属性窗口把文件的Build Action设置为Resource 一般情况下如果Build Action设置为Resource 则Copy to Output Directory设为Do not copy

不希望以资源形式使用外部文件,可以啊Build Action 设为None 把Copy to Output Directory 设为Copy always

10.4  使用Pack URi路径访问二进制资源

pack://application,,,[/程序集名称;][可选版本;][文件夹名称/]文件名称

[文件夹名称/]文件名称

11  深入浅出话模板

 11.2  数据的外衣DataTemplate

需求:有一列汽车数据,这列数据显示在ListBox的条目显示汽车的厂商图标和简要参数,单击某个条目后在窗体的详细内容区域显示汽车的照片和详细参数

模式1:事件驱动

<UserControl x:Class="WpfApp4.UserControl2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp4"
       >
    <Border BorderBrush="black" BorderThickness="1" CornerRadius="6">
        <StackPanel Margin="5">
            <Image x:Name="imagePhoto" Width="400" Height="250"/>
            <StackPanel Orientation="Horizontal" Margin="5,0">
                <TextBlock Text="Name:" FontWeight="Bold" FontSize="20"/>
                <TextBlock x:Name="textBlockName" FontSize="20" Margin="5,0"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="5,0">
                <TextBlock Text="Automaker:" FontWeight="Bold" FontSize="20"/>
                <TextBlock x:Name="textBlockAutomaker" FontSize="20" Margin="5,0"/>
                <TextBlock Text="Year:" FontWeight="Bold" FontSize="20"/>
                <TextBlock x:Name="textBlockYear" FontSize="20" Margin="5,0"/>
                <TextBlock Text="Top Speed:" FontWeight="Bold" FontSize="20"/>
                <TextBlock x:Name="textBlockTopSpeed" FontSize="20" Margin="5,0"/>
            </StackPanel>

        </StackPanel>



    </Border>
</UserControl>
usercontr2_xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using static WpfApp4.MainWindow;

namespace WpfApp4
{
    /// <summary>
    /// UserControl2.xaml 的交互逻辑
    /// </summary>
    public partial class UserControl2 : UserControl
    {
        public UserControl2()
        {
            InitializeComponent();
        }

        private Car car;
        public Car Car
        {
            get { return car; }
            set 
            {
                car = value;
                this.textBlockName.Text = car.Name;
                this.textBlockYear.Text = car.Year;
                this.textBlockTopSpeed.Text = car.TopSpeed;
                this.textBlockAutomaker.Text = car.Automaker;            
                string uriStr = string.Format(@"/Images/{0}.png", car.Name);
                this.imagePhoto.Source = new BitmapImage(new Uri(uriStr, UriKind.Relative));
            }
        }
    }
}
usercontr2_xaml.cs
<UserControl x:Class="WpfApp4.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp4"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid Margin="2">
        <StackPanel Orientation="Horizontal">
            <Image x:Name="imageLogo" Grid.RowSpan="3" Width="64" Height="64"/>
            <StackPanel Margin="5,10">
                <TextBlock x:Name="textBlockName" FontSize="16" FontWeight="Bold"/>
                <TextBlock x:Name="textBlockYear" FontSize="14"/>

            </StackPanel>

        </StackPanel>
    </Grid>
</UserControl>
usercontrol1_xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using static WpfApp4.MainWindow;

namespace WpfApp4
{
    /// <summary>
    /// UserControl2.xaml 的交互逻辑
    /// </summary>
    public partial class UserControl2 : UserControl
    {
        public UserControl2()
        {
            InitializeComponent();
        }

        private Car car;
        public Car Car
        {
            get { return car; }
            set 
            {
                car = value;
                this.textBlockName.Text = car.Name;
                this.textBlockYear.Text = car.Year;
                this.textBlockTopSpeed.Text = car.TopSpeed;
                this.textBlockAutomaker.Text = car.Automaker;            
                string uriStr = string.Format(@"/Images/{0}.png", car.Name);
                this.imagePhoto.Source = new BitmapImage(new Uri(uriStr, UriKind.Relative));
            }
        }
    }
}
usercontrol1_xaml.cs
<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:prop="clr-namespace:WpfApp4.Properties"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <StackPanel Orientation="Horizontal" Margin="5">
        <local:UserControl2 x:Name="detailView"/>
        <ListBox x:Name="listBoxCars" Width="180" Margin="5,0"
                 SelectionChanged="listBoxCars_SelectionChanged"/>
    </StackPanel>             


</Window>
mainview_xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

            InitialCarList();
           
         
        }

        //选择变化事件的处理器
        private void listBoxCars_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            UserControl1 view = e.AddedItems[0] as UserControl1;
            if (view!=null)
            {
                this.detailView.Car = view.Car;
            }
        }
        public class Car
        {
            public string Automaker { get; set; }
            public string Name { get; set; }
            public string Year { get; set; }
            public string TopSpeed { get; set; }
        }

        //初始化listBox
        private void InitialCarList()
        {
            List<Car> carList = new List<Car>()
            {
                new Car(){ Automaker="Lamborghini",Name="Diablo",Year="1990",TopSpeed="340"},
                new Car(){ Automaker="Lamborghini",Name="Murcielago",Year="2001",TopSpeed="325"},

            };
            foreach (Car car in carList)
            {
                UserControl1 view = new UserControl1();
                view.Car = car;
                this.listBoxCars.Items.Add(view);
            }
        }
        
        



    }



   



    
}
maniview_xaml.cs

模式2:数据驱动

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media.Imaging;

namespace WpfApp4
{
    //厂商名称转换为Logo图片路径
    public class AutomakerToLogoPathConvert : IValueConverter
    {
        //正向转化
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string uriStr = string.Format(@"/Logos/{0}.png", (string)value);
            return new BitmapImage(new Uri(uriStr, UriKind.Relative));
        }
        //未被用到
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    //汽车名称转换为照片路径
    public class NmaeToLogoPathConvert : IValueConverter
    {
        //正向转化
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string uriStr = string.Format(@"/Images/{0}.png", (string)value);
            return new BitmapImage(new Uri(uriStr, UriKind.Relative));
        }
        //未被用到
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
convert.cs
<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <!--converters-->
        <local:AutomakerToLogoPathConvert x:Key="a21"/>
        <local:NmaeToLogoPathConvert x:Key="n2p"/>
        <!--DataTemplate for Detail View-->
        <DataTemplate x:Key="carDetaiIViewTemplate">
            <Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
                <StackPanel Margin="5">
                    <Image Width="400" Height="250"
                                     Source="{Binding Name,Converter={StaticResource n2p}}"/>
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <TextBlock Text="Name" FontWeight="Bold" FontSize="20"/>
                        <TextBlock Text="{Binding Name}" FontSize="20" Margin="5,0"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="5,0">
                        <TextBlock Text="Automaker" FontWeight="Bold" FontSize="20"/>
                        <TextBlock Text="{Binding Automaker}" FontSize="20" Margin="5,0"/>
                        <TextBlock Text="Year" FontWeight="Bold" FontSize="20"/>
                        <TextBlock Text="{Binding Year}" FontSize="20" Margin="5,0"/>
                        <TextBlock Text="Top Speed" FontWeight="Bold" FontSize="20"/>
                        <TextBlock Text="{Binding TopSpeed}" FontSize="20" Margin="5,0"/>
                    </StackPanel>
                </StackPanel>
            </Border>
        </DataTemplate>
        <!--DataTemplate for Item View-->
        <DataTemplate x:Key="carListItemViewTemplate">
            <Grid Margin="2">
                <StackPanel Orientation="Horizontal">
                    <Image Source="{Binding Automaker,Converter={StaticResource a21}}"
                           Grid.RowSpan="3" Width="64" Height="64"/>
                    <StackPanel Margin="5,10">
                        <TextBlock Text="{Binding Name}" FontSize="16" FontWeight="Bold"/>
                        <TextBlock Text="{Binding Year}" FontSize="14"/>
                    </StackPanel>
                    
                </StackPanel>
             </Grid>
                  
        </DataTemplate>
    </Window.Resources>
    <!--窗体内容-->
    <StackPanel Orientation="Horizontal" Margin="5">
        <UserControl ContentTemplate="{StaticResource  carDetaiIViewTemplate}"
                     Content="{Binding SelectedItem,ElementName=listBoxCars}"/>
        <ListBox x:Name="listBoxCars" Width="180" Margin="5,0"
                 ItemTemplate="{StaticResource carListItemViewTemplate}"/>

    </StackPanel>
</Window>
mainWindow.xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            InitialCarList();



        }

        public class Car
        {
            public string Automaker { get; set; }
            public string Name { get; set; }
            public string Year { get; set; }
            public string TopSpeed { get; set; }
        }

        //初始化listBox
        private void InitialCarList()
        {
            List<Car> carList = new List<Car>()
            {
                new Car(){ Automaker="Lamborghini",Name="Diablo",Year="1990",TopSpeed="340"},
                new Car(){ Automaker="Lamborghini",Name="Murcielago",Year="2001",TopSpeed="325"},

            };
            //填充数据源
            this.listBoxCars.ItemsSource = carList;
        }


    }


}



   



    
mainWindow.cs

 11.3  控件的外衣ControlTemplate

11.3.2  ItemsConteol的PanelTemplate

11.4  DataTemplate与ControlTemplate的关系与应用

11.4.1  DataTemplate与ControlTemplate的关系

11.4.2  DataTemplate与ControlTemplate的应用

把ControlTemplate应用在所有目标上需要借助Style来实现,但Stayle不能标记x:Key例如如下代码

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBox}">
                        <Border x:Name="Bd" SnapsToDevicePixels="True"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="5">
                            <ScrollViewer x:Name="PART_ContentHost"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Margin" Value="5"/>
            <Setter Property="BorderBrush" Value="black"/>
            <Setter Property="Height" Value="25"/>
        </Style>
    </Window.Resources>
    <StackPanel>
        <TextBox/>
        <TextBox/>
        <TextBox Style="{x:Null}" Margin="5"/>
    </StackPanel>
</Window>
xaml

把DataTemplate应用在某个数据类型伤感的方法市设置DataTemplate的DataType属性,并且DataTemplate作为资源时不能带有x:Key标记

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
    <!--DataTemplate-->
        <DataTemplate DataType="{x:Type local:Unit}"    >
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <Grid>
                        <Rectangle Stroke="Yellow" Fill="Orange" Width="{Binding price}"/>
                        <TextBlock Text="{Binding Year}"/>
                    </Grid>
                    <TextBlock Text="{Binding price}" Margin="5,0"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
        <!--数据源-->
        <c:ArrayList x:Key="ds">
            <local:Unit Year="2001" price="100"/>
            <local:Unit Year="2002" price="150"/>
            <local:Unit Year="2003" price="180"/>
            <local:Unit Year="2004" price="190"/>
            <local:Unit Year="2005" price="120"/>
            <local:Unit Year="2006" price="130"/>
            <local:Unit Year="2007" price="150"/>
        </c:ArrayList>
    </Window.Resources>
    <StackPanel>
        <ListBox ItemsSource="{StaticResource ds}"></ListBox>
        <ComboBox ItemsSource="{StaticResource ds}" Margin="5"/>
    </StackPanel>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();



        }



    }
    public class Unit
    { 
        public int price { get; set; }
        public string Year { get; set; }
    }

}



   



    
xaml.cs

当数据是以XML形式存储时,DataTemplate具有直接把XML数据结点当作目标对象的功能——XML数据中元素名可直接作为DataType,元素的子节点可以使用XPath来访问

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
    <!--DataTemplate-->
        <DataTemplate DataType="Unit"    >
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <Grid>
                        <Rectangle Stroke="Yellow" Fill="Orange" Width="{Binding XPath=@Price}"/>
                        <TextBlock Text="{Binding XPath=@Year}"/>
                    </Grid>
                    <TextBlock Text="{Binding XPath=@Price}" Margin="5,0"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
        <!--数据源-->
        <XmlDataProvider x:Key="ds" XPath="Units/Unit">
            <x:XData>
                <Units xmlns="">
                    <Unit Year="2000" Price="100"/>
                    <Unit Year="2001" Price="120"/>
                    <Unit Year="2002" Price="140"/>
                    <Unit Year="2003" Price="160"/>
                    <Unit Year="2004" Price="180"/>
                    <Unit Year="2005" Price="200"/>
                </Units>
            </x:XData>
        </XmlDataProvider>
    </Window.Resources>
    <StackPanel>
        <ListBox ItemsSource="{Binding Source={StaticResource ds}}"></ListBox>
        <ComboBox ItemsSource="{Binding Source={StaticResource ds}}" Margin="5"/>
    </StackPanel>
</Window>
xaml

使用TreeView显示多层级,不同类型数据

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <!--数据源-->
        <XmlDataProvider x:Key="ds" Source="Data.xml" XPath="Data/Grade"/>
        <!--年级模板-->
        <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">
            <TextBlock Text="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
        <!--班级模板-->
        <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
            <RadioButton Content="{Binding XPath=@Name}" GroupName="gn"/>
        </HierarchicalDataTemplate>
        <!--小组模板--> 
        <HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding XPath=Student}">
            <CheckBox Content="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <TreeView Margin="5" ItemsSource="{Binding Source={StaticResource ds}}"/>
    </Grid>
   
</Window>
xaml

同一种数据类型的嵌套结构,只需要设计一个HierachicalDataTemplate就好了,它会自动迭代应用效果

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <!--数据源-->
        <XmlDataProvider x:Key="ds" Source="Data.xml" XPath="Data/Operation"/>
        <!--Operation-->
        <HierarchicalDataTemplate DataType="Operation" ItemsSource="{Binding XPath=Operation}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding XPath=@Name}" Margin="10,0"/>
                <TextBlock Text="{Binding XPath=@Gesture}" Margin="10,0"/>
            </StackPanel>

        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid MenuItem.Click="Grid_Click">
        <Menu ItemsSource="{Binding Source={StaticResource ds}}"/>
    </Grid>
   
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();



        }

        private void Grid_Click(object sender, RoutedEventArgs e)
        {
            MenuItem mi = e.OriginalSource as MenuItem;
            XmlElement xe = mi.Header as XmlElement;
            MessageBox.Show(xe.Attributes["Name"].Value);
        }
    }


}



   



    
xaml.cs
<?xml version="1.0" encoding="utf-8" ?>
<Data xmlns="">
    <Operation Name="文件">
        <Operation Name="新建" Gesture="N">            
                <Operation Name="项目" Gesture="Control+P"/>
                <Operation Name="网站" Gesture="Control+W"/>
                <Operation Name="文档" Gesture="Control+D"/>
        </Operation>
        <Operation Name="保存" Gesture="Control+S"/>
        <Operation Name="打印" Gesture="Control+P"/>
        <Operation Name="退出" Gesture="Control+X"/>                
        </Operation>
    <Operation Name="编辑" >
        <Operation Name="拷贝" Gesture="Control+C"/>
        <Operation Name="剪切" Gesture="Control+X"/>
        <Operation Name="粘贴" Gesture="Control+V"/>
    </Operation>
    
</Data>
XML

11.4.3  寻找失落的控件

寻找由ControlTempate生成的控件

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <ControlTemplate x:Key="cTmp">
            <StackPanel Background="Orange" >
                <TextBox x:Name="textBox1" Margin="6"/>
                <TextBox x:Name="textBox2" Margin="6,0"/>
                <TextBox x:Name="textBox3" Margin="6"/>
            </StackPanel>
        </ControlTemplate>
    </Window.Resources>
    <StackPanel Background="Yellow">
        <UserControl x:Name="uc" Template="{StaticResource cTmp}" Margin="5"/>
        <Button Content="Find by Name" Width="120" Height="30" Click="Button_Click"/>
    </StackPanel>
   
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }



        private void Button_Click(object sender, RoutedEventArgs e)
        {
            TextBox tb = this.uc.Template.FindName("textBox1", this.uc) as TextBox;
            tb.Text = "Hello WPF";
            StackPanel sp = tb.Parent as StackPanel;
            (sp.Children[1] as TextBox).Text = "Hello ControlTemple";
            (sp.Children[2] as TextBox).Text = "I can find you!";
        }
    }


}



   



    
xaml.cs

寻找由DataTemplate生成的控件

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
    <!--数据对象-->
        <local:Student x:Key="stu" Id="1" Name="Timothy" Skill="WPF" HasJob="True"/>
        <!--DataTemplate-->
        <DataTemplate x:Key="stuDT">
            <Border BorderBrush="Orange" BorderThickness="2" CornerRadius="5">
                <StackPanel>
                    <TextBlock Text="{Binding Id}" Margin="5"/>
                    <TextBlock x:Name="textBlockName" Text="{Binding Name}" Margin="5"/>
                    <TextBlock Text="{Binding Skill}" Margin="5"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <!--主体布局-->
    <StackPanel>
        <ContentPresenter x:Name="cp" Content="{StaticResource stu}"
                          ContentTemplate="{StaticResource stuDT}" Margin="5"/>
        <Button Content="Find" Margin="5,0" Click="Button_Click"/>
    </StackPanel>
   
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            TextBlock tb = this.cp.ContentTemplate.FindName("textBlockName", this.cp) as TextBlock;
            MessageBox.Show(tb.Text);

            //Student stu = this.cp.Content as Student;
            //MessageBox.Show(stu.Name);
        }
    }

    public class Student
    { 
        public int Id { get; set; }
        public string Name { get; set; }
        public string Skill { get; set; }
        public bool HasJob { get; set; }
    }

}



   



    
xaml.cs
<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
<!--数据集合-->
        <c:ArrayList x:Key="stuList">
            <local:Student Id="1" Name="Timoty" Skill="WPF" HasJob="True"/>
            <local:Student Id="2" Name="Timoty1" Skill="WPF1" HasJob="False"/>
            <local:Student Id="3" Name="Timoty2" Skill="WPF2" HasJob="True"/>
            <local:Student Id="4" Name="Timoty3" Skill="WPF3" HasJob="False"/>
            <local:Student Id="5" Name="Timoty4" Skill="WPF4" HasJob="True"/>
        </c:ArrayList>
        <!--DataTemplate-->
        <DataTemplate x:Key="nameDT">
            <TextBox x:Name="textBoxName" Text="{Binding Name}" GotFocus="textBoxName_GotFocus"/>
        </DataTemplate>
        <DataTemplate x:Key="skillDT">
            <TextBox x:Name="textBoxSkill" Text="{Binding Skill}"/>
        </DataTemplate>
        <DataTemplate x:Key="hjDT">
            <CheckBox x:Name="checkBoxJob" IsChecked="{Binding HasJob}"/>
        </DataTemplate>
    </Window.Resources>
<!--主体布局-->
    <Grid Margin="5">
        <ListView x:Name="listViewStudetn" ItemsSource="{StaticResource stuList}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}"/>
                    <GridViewColumn Header="姓名" CellTemplate="{StaticResource nameDT}"/>
                    <GridViewColumn Header="技术" CellTemplate="{StaticResource skillDT}"/>
                    <GridViewColumn Header="已工作" CellTemplate="{StaticResource hjDT}" />
                </GridView>
            </ListView.View>
            
        </ListView>
        
    </Grid>
</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void textBoxName_GotFocus(object sender, RoutedEventArgs e)
        {
            //访问业务逻辑数据
            TextBox tb = e.OriginalSource as TextBox;   //获取事件发起的源头
            ContentPresenter cp = tb.TemplatedParent as ContentPresenter;//获取模板目标
            Student stu = cp.Content as Student;//获取业务逻辑
            this.listViewStudetn.SelectedItem = stu;//设置ListView的选中项

            //访问界面元素
            ListViewItem lvi = this.listViewStudetn.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;
            CheckBox chb = this.FindVisualChild<CheckBox>(lvi);
            MessageBox.Show(chb.Name);

        }


        private ChildType FindVisualChild<ChildType>(DependencyObject obj)
            where ChildType : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is ChildType)
                {
                    return child as ChildType;
                }
                else
                {
                    ChildType childOfChiild = FindVisualChild<ChildType>(child);
                    if (childOfChiild != null)
                    {
                        return childOfChiild;
                    }
                }
            }
            return null;
        }
    }


    public class Student
    { 
        public int Id { get; set; }
        public string Name { get; set; }
        public string Skill { get; set; }
        public bool HasJob { get; set; }
    }

}



   



    
xaml.cs

11.5  深入浅出话Style  

11.5.1  styel中的setter

11.5.2  styel中的Trigger

1.基本的Trigger

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <Style TargetType="CheckBox" >
            <Style.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Trigger.Setters >
                        <Setter Property="FontSize" Value="20"/>
                        <Setter Property="Foreground"  Value="Orange"/>
                    </Trigger.Setters>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <CheckBox Content="悄悄的我走了" Margin="5"/>
        <CheckBox Content="正如我悄悄的来" Margin="5"/>
        <CheckBox Content="我挥一挥衣袖" Margin="5"/>
        <CheckBox Content="不带走一片云彩" Margin="5"/>
    </StackPanel>
</Window>
xaml

2.MuitiTrigger

多个条件满足才会触发

3.由数据触发的DataTrigger

长度小于6 边框显示为红色

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <local:L2BConvert x:Key="cvtr"/>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <DataTrigger  
                    Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text.Length, 
                    Converter={StaticResource cvtr}}" Value="false">
                    <Setter Property="BorderBrush" Value="Red"/>
                    <Setter Property="BorderThickness" Value="1"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <TextBox Margin="5"/>
        <TextBox Margin="5"/>
        <TextBox Margin="5"/>
    </StackPanel>

</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }


    }

    public class L2BConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int textLengrh = (int)value;
            return textLengrh > 6 ? true : false;
        }

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



   



    
xaml.cs

4.多数据条件触发的MultiDataTrigger

 需求:用户界面上使用ListBox显示了一列Student数据,当数据同时满足Id为2、Name为Tom时,条目高亮。

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <Style TargetType="ListBoxItem">
            <!--使用Style设置DataTemplate-->
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Id}" Width="60"/>
                            <TextBlock Text="{Binding Name}" Width="120"/>
                            <TextBlock Text="{Binding Age}" Width="60"/>
                        </StackPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
            <!--MultiDataTrigger-->
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Id}" Value="2"/>
                        <Condition Binding="{Binding Path=Name}" Value="Tom"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.Setters>
                        <Setter Property="Background" Value="Orange"/>
                    </MultiDataTrigger.Setters>
                </MultiDataTrigger>
            </Style.Triggers>
            
        </Style>
    </Window.Resources>
    <StackPanel>
        <ListBox x:Name="listBoxStudet" Margin="5"/>
    </StackPanel>

</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;


namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            //初始化listbox
            List<Student> stuList = new List<Student>()
            {
                new Student(){Id=1,Name="Tom2",Age=10},
                new Student(){Id=2,Name="Tom",Age=11},
                new Student(){Id=3,Name="Tom3",Age=11}

            };
            this.listBoxStudet.ItemsSource = stuList;
        }


    }
    public class Student
    { 
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age{ get; set; }
    }
   
}



   



    
xaml.cs

5.由事件触发的EventTrigger

又事件触发触发后是执行一段动画

下面例子中创建了一个针对Button的Style,这个Syle包含两个EventTrigger,一个由MouseEvnet事件触发,另一个由MouseLeave事件触发.

鼠标进入,button变大,鼠标离开,button变小

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">
    <Window.Resources>
        <Style TargetType="Button">
            <Style.Triggers>
                <!--鼠标进入-->
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Width" />
                            <DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Height" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <!--鼠标离开-->
                <EventTrigger RoutedEvent="MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation  Duration="0:0:0.2" Storyboard.TargetProperty="Width" />
                            <DoubleAnimation  Duration="0:0:0.2" Storyboard.TargetProperty="Height" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Canvas>
        <Button Width="40" Height="40" Content="OK"/>
    </Canvas>


</Window>
xaml

 

12.4  动画

12.4.1  简单动画

1.简单线性动画

变化时间Duration:必须指定

变化终点To:如果没有指定,程序将采用上一次动画的终点或默认值。

变化幅度By:如果同时指定了变化终点,变化幅度将被忽略。

变化起点From:如果没有指定变化起点则以变化目标的当前值为起点。

需求:用户界面上有Button按钮,每次点击Button时,会改变Button的显示位置

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">

    <Grid>
        <Button Content="Move!" HorizontalAlignment="Left" VerticalAlignment="Top"
                Width="60" Height="60" Click="Button_Click">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="0" Y="0"/>
            </Button.RenderTransform>
            
        </Button>
    </Grid>


</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;
using System.Windows.Media.Animation;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation daX = new DoubleAnimation();
            DoubleAnimation daY = new DoubleAnimation();

            //指定起点
            //daX.From = 0D;
            //daY.From = 0D;
            //指定幅度
            daX.By = 100D;
            daY.By = 100D;
            ////指定终点
            //Random r = new Random();
            //daX.To = r.NextDouble() * 300;
            //daY.To = r.NextDouble() * 300;
            //指定时长
            Duration duration = new Duration(TimeSpan.FromMilliseconds(30));
            daX.Duration = duration;
            daY.Duration = duration;
            //动画主体 是TranslateTransform变形非Button
            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);

        }
    }
   
}



   



    
xaml.cs

2.  高级动画控制

AccelerationRadion  加速速率,介于0.0和1.0之间,与Deceleration之和不大于1.0     模拟汽车启动

DecelerationRadion  减速速率,介于0.0和1.0之间,与Acceleration之和不大于1.0     模拟汽车刹车

SpeedRadion       动画实际播放与正常速度比值                  快进播放、慢动作

AutoReverse     是否以相反动画方式从终止值返回起始值             倒退播放

RepeatBehavior        动画的重复行为,取0不播放,使用double类型值可控制循环次数,

           取RepeatBehavior.Forever为永远循环              循环播放

BeginTime      正式开始播放前的等待时间                   多个动画之间的协同  

EasingFunction      缓冲式渐变                          乒乓球跳效果

案例:乒乓球弹跳式的效果

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">

    <Grid>
        <Button Content="Move!" HorizontalAlignment="Left" VerticalAlignment="Top"
                Width="60" Height="60" Click="Button_Click">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="0" Y="0"/>
            </Button.RenderTransform>
            
        </Button>
    </Grid>


</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;
using System.Windows.Media.Animation;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation daX = new DoubleAnimation();
            DoubleAnimation daY = new DoubleAnimation();

            //指定起点
            BounceEase be = new BounceEase();
            be.Bounces = 3;//弹跳3次
            be.Bounciness = 3;//弹性程度,值越大反弹越低
            daY.EasingFunction = be;
            //指定终点

            daX.To = 300;
            daY.To = 300;

            //指定时长
            Duration duration = new Duration(TimeSpan.FromMilliseconds(2000));
            daX.Duration = duration;
            daY.Duration = duration;

            //动画主体 是TranslateTransform变形非Button
            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);

        }
    }
   
}



   



    
xaml.cs

3.  关键帧动画

关键帧动画允许程序员为一段动画设置几个”里程碑“ 动画执行到里程碑所在的关键的时间点时,被动画所控制的属性值也必须达到设定的值。

案例:button按照z字型动作

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">

    <Grid>
        <Button Content="Move!" HorizontalAlignment="Left" VerticalAlignment="Top"
                Width="60" Height="60" Click="Button_Click">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="0" Y="0"/>
            </Button.RenderTransform>
            
        </Button>
    </Grid>


</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;
using System.Windows.Media.Animation;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimationUsingKeyFrames daX = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames daY = new DoubleAnimationUsingKeyFrames();

            //设置动画总时长
            daX.Duration = new Duration(TimeSpan.FromMilliseconds(900));
            daY.Duration = new Duration(TimeSpan.FromMilliseconds(900));

            //创建、添加关键帧
            LinearDoubleKeyFrame x_kf_1 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame x_kf_2 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame x_kf_3 = new LinearDoubleKeyFrame();

            x_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
            x_kf_1.Value = 200;
            x_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
            x_kf_2.Value = 0;
            x_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
            x_kf_3.Value = 200;

            daX.KeyFrames.Add(x_kf_1);
            daX.KeyFrames.Add(x_kf_2);
            daX.KeyFrames.Add(x_kf_3);


            LinearDoubleKeyFrame y_kf_1 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame y_kf_2 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame y_kf_3 = new LinearDoubleKeyFrame();

            y_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
            y_kf_1.Value = 0;
            y_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
            y_kf_2.Value = 180;
            y_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
            y_kf_3.Value = 180;

            daY.KeyFrames.Add(y_kf_1);
            daY.KeyFrames.Add(y_kf_2);
            daY.KeyFrames.Add(y_kf_3);



         
            //动画主体 是TranslateTransform变形非Button
            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);

        }
    }
   
}



   



    
xaml.cs

4.  特殊的关键帧

DoubleAnimationUsingFrames的KeyFrames属性的数据类型时DoubleKeyFrameCollection,此类集合可接收的元素类型为DoubleKeyFrame。DoubleKeyFrame是一个抽象类

DoubleKeyFrame的所有派生类如下

 LinearDoubleKeyFrame:线性变化关键帧,目标属性值的变化是直线的、均匀的,即变化的速率不变。

DiscreteDoubleKeyFrame:不连续变化关键帧,目标属性值是跳跃性、跃迁性的。

SplineDoubleKeyFrame:样条函数式变化关键帧,目标属性值的变化速率式一条贝塞尔曲线。

EasingDoubleKeyFrame:缓冲样式变化关键帧,目标属性值以某种缓冲形式变化。

 SplineDoubleKeyFrame案例

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">

    <Grid>
        <Button Content="Move!" HorizontalAlignment="Left" VerticalAlignment="Top"
                Width="60" Height="60" Click="Button_Click">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="0" Y="0"/>
            </Button.RenderTransform>
            
        </Button>
    </Grid>


</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;
using System.Windows.Media.Animation;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //创建动画
            DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames();
            dakX.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
            //创建、添加关键帧
            SplineDoubleKeyFrame kf = new SplineDoubleKeyFrame();
            kf.KeyTime = KeyTime.FromPercent(1);
            kf.Value = 400;
            KeySpline ks = new KeySpline();
            ks.ControlPoint1 = new Point(0, 1);
            ks.ControlPoint2 = new Point(1, 0);
            kf.KeySpline = ks;
            dakX.KeyFrames.Add(kf);

            //执行动画
            this.tt.BeginAnimation(TranslateTransform.XProperty, dakX);

  

        }
    }
   
}



   



    
xaml.cs

 5.路径动画

让目标对象沿着给定的路径移动,使用DoubleAnimationUsingPath类,DoubleAnimationUsingPath类需要一个PathGeometry来指明移动路径,Pathgeometry的数据信息可以用AML的Path语法书写。

PathGeometry的重要属性式Source,Source数据类型的取值是PathAnimationSource枚举,

枚举取X时,意味着这个动画关注的是曲线上每一点横坐标的变化。

枚举取Y时,意味着这个动画关注的是曲线上每一点纵坐标的变化。

枚举取Angle时,意味着这个动画关注的是曲线上每一点切线方向的变化。

案例:让一个Button沿着一条贝塞尔曲线做波浪运动

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">

    <Grid x:Name="LayoutRoot">
        <Grid.Resources>
            <!--移动路径-->
            <PathGeometry x:Key="movingPath" Figures="M 0,150 C300,-100 300,400 600,120"/>
        </Grid.Resources>
        <Button Content="Move" HorizontalAlignment="Left" VerticalAlignment="Top"  Width="80" Height="80" Click="Button_Click">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="0" Y="0"/>
            </Button.RenderTransform>
            
        </Button>
    </Grid>


</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;
using System.Windows.Media.Animation;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //从XAMl代码中获取移动路径数据
            PathGeometry pg = this.LayoutRoot.FindResource("movingPath") as PathGeometry;
            Duration duration = new Duration(TimeSpan.FromMilliseconds(600));
            //创建动画
            DoubleAnimationUsingPath dapX = new DoubleAnimationUsingPath();
            dapX.PathGeometry = pg;
            dapX.Source = PathAnimationSource.X;
            dapX.Duration = duration;

            DoubleAnimationUsingPath dapY = new DoubleAnimationUsingPath();
            dapY.PathGeometry = pg;
            dapY.Source = PathAnimationSource.Y;
            dapY.Duration = duration;

            //自动返回、永远循环
            dapX.AutoReverse = true;
            dapX.RepeatBehavior = RepeatBehavior.Forever;
            dapY.AutoReverse = true;
            dapY.RepeatBehavior = RepeatBehavior.Forever;

            //执行动画
            this.tt.BeginAnimation(TranslateTransform.XProperty, dapX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, dapY);

        }
    }
   
}



   



    
xaml.cs

12.4.2  场景

场景(StoryBoard)并行执行的一组动画

案例

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"   Title="123t"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        mc:Ignorable="d"
        x:Name="window_1"  Height="350" Width="623">

    <Grid Margin="6">
        <!--布局控制-->
        <Grid.RowDefinitions>
            <RowDefinition Height="38"/>
            <RowDefinition Height="38"/>
            <RowDefinition Height="38"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition  Width="60"/>
        </Grid.ColumnDefinitions>
        <!--跑道红-->
        <Border BorderBrush="Gray" BorderThickness="1" Grid.Row="0">
            <Ellipse x:Name="ballR" Height="36" Width="36" Fill="Red" HorizontalAlignment="Left">
                <Ellipse.RenderTransform>
                    <TranslateTransform x:Name="ttR"/>
                </Ellipse.RenderTransform>
            </Ellipse>
        </Border>
        <!--跑道绿-->
        <Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="1">
            <Ellipse x:Name="ballG" Height="36" Width="36" Fill="LawnGreen"  HorizontalAlignment="Left">
                <Ellipse.RenderTransform>
                    <TranslateTransform x:Name="ttG"/>
                </Ellipse.RenderTransform>
            </Ellipse>
        </Border>
        <!--跑道蓝-->
        <Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="2">
            <Ellipse x:Name="ballB" Height="36" Width="36" Fill="Blue"  HorizontalAlignment="Left">
                <Ellipse.RenderTransform>
                    <TranslateTransform x:Name="ttB"/>
                </Ellipse.RenderTransform>
            </Ellipse>
        </Border>
        <!--按钮-->
        <Button Content="Go!" Grid.Column="1" Grid.RowSpan="3" Click="Button_Click"/>
    </Grid>


</Window>
xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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;
using System.ComponentModel;//使用INotifyPropertyChanged
using System.Data;
using System.Xml;
using System.Globalization;
using System.IO;
using System.Windows.Media.Animation;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Duration duration = new Duration(TimeSpan.FromMilliseconds(600));
            //红球匀速移动
            DoubleAnimation daRx = new DoubleAnimation();
            daRx.Duration = duration;
            daRx.To = 400;
            //绿球变速运动
            DoubleAnimationUsingKeyFrames dakGx = new DoubleAnimationUsingKeyFrames();
            dakGx.Duration = duration;
            SplineDoubleKeyFrame kfG = new SplineDoubleKeyFrame(400, KeyTime.FromPercent(1.0));
            kfG.KeySpline = new KeySpline(1, 0, 0, 1);
            dakGx.KeyFrames.Add(kfG);
            //蓝球变速运动
            DoubleAnimationUsingKeyFrames dakBx = new DoubleAnimationUsingKeyFrames();
            dakBx.Duration = duration;
            SplineDoubleKeyFrame kfB = new SplineDoubleKeyFrame(400, KeyTime.FromPercent(1.0));
            kfB.KeySpline = new KeySpline(0, 1, 1, 0);
            dakBx.KeyFrames.Add(kfB);
            //创建场景
            Storyboard storyboard = new Storyboard();

            Storyboard.SetTargetName(daRx, "ttR");
            Storyboard.SetTargetProperty(daRx, new PropertyPath(TranslateTransform.XProperty));

            Storyboard.SetTargetName(dakGx, "ttG");
            Storyboard.SetTargetProperty(dakGx, new PropertyPath(TranslateTransform.XProperty));

            Storyboard.SetTargetName(dakBx, "ttB");
            Storyboard.SetTargetProperty(dakBx, new PropertyPath(TranslateTransform.XProperty));

            storyboard.Duration = duration;
            storyboard.Children.Add(daRx);
            storyboard.Children.Add(dakGx);
            storyboard.Children.Add(dakBx);

            storyboard.Begin(this);
            storyboard.Completed += (a,b) =>{ MessageBox.Show(ttG.X.ToString());};
            
        }
    }
   
}



   



    
xaml.cs
原文地址:https://www.cnblogs.com/suwencjp/p/15628071.html