GIF动画、滚动条同步、DataGrid列锁定/行头/行高/鼠标事件、Auto与*区别、绝对定位、ToolTip样式、Binding技巧等

41-WPF中显示GIF动画图片-WpfAnimatedGif

这里使用的是第三方组件,可以通过控制台或者Nuget安装

Install-Package WpfAnimatedGif
xmlns:gif="http://wpfanimatedgif.codeplex.com"
<Image gif:ImageBehavior.AnimatedSource="Images/animated.gif" />Code language: HTML, XML (xml)

GitHub地址: https://github.com/XamlAnimatedGif/WpfAnimatedGif

<Window x:Class="Gif.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:Gif"
        xmlns:gif="http://wpfanimatedgif.codeplex.com"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Image gif:ImageBehavior.AnimatedSource="load.gif" />
    </Grid>
</Window>Code language: HTML, XML (xml)

42-WPF同步两个滚动条的位置

首先我们准备两个表格 同时绑定到一个数据源上面

<Window x:Class="DataGridDemo.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:DataGridDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Column="0" x:Name="dataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Width="80" Binding="{Binding Name}"/>
                <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age}"/>
                <DataGridHyperlinkColumn Header="Email" Width="150" 
                                         Binding="{Binding Email}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid Grid.Column="1" x:Name="dataGrid2" ItemsSource="{Binding}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Width="80" Binding="{Binding Name}"/>
                <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age}"/>
                <DataGridHyperlinkColumn Header="Email" Width="150" 
                                         Binding="{Binding Email}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>Code language: HTML, XML (xml)
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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 DataGridDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            ObservableCollection<Member> memberData = new ObservableCollection<Member>();
            memberData.Add(new Member()
            {
                Name = "Joe",
                Age = "23",
                Email = new Uri("mailto:Joe@school.com")
            });
            memberData.Add(new Member()
            {
                Name = "Mike",
                Age = "20",
                Email = new Uri("mailto:Mike@school.com")
            });
            memberData.Add(new Member()
            {
                Name = "Lucy",
                Age = "25",
                Email = new Uri("mailto:Lucy@school.com")
            });

            // ... 此处省略大量重复数据添加代码,实际使用时按需添加 ...

            dataGrid.DataContext = memberData;
            dataGrid2.DataContext = memberData;
        }
    }

    public class Member
    {
        public string Name { get; set; }
        public string Age { get; set; }
        public Uri Email { get; set; }
    }
}Code language: HTML, XML (xml)

利用滚动条的ScrollChanged事件,同步两个滚动条的位置。

下面是水平进度条同步

ScrollViewer sv1, sv2;

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    //分别获取两个DataGrid的ScrollViewer
    sv1 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.dataGrid, 0), 0) as ScrollViewer;
    sv2 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.dataGrid2, 0), 0) as ScrollViewer;

    //关联ScrollChanged事件
    sv1.ScrollChanged += new ScrollChangedEventHandler(sv1_ScrollChanged);
    sv2.ScrollChanged += new ScrollChangedEventHandler(sv2_ScrollChanged);
}

void sv1_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    sv2.ScrollToHorizontalOffset(sv1.HorizontalOffset);
}

void sv2_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    sv1.ScrollToHorizontalOffset(sv2.HorizontalOffset);
}Code language: JavaScript (javascript)

然后下面是垂直进度条

public partial class MainWindow : Window
{
    ScrollViewer sv1, sv2;

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        //分别获取两个DataGrid的ScrollViewer
        sv1 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.dataGrid, 0), 0) as ScrollViewer;
        sv2 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.dataGrid2, 0), 0) as ScrollViewer;

        //关联ScrollChanged事件
        sv1.ScrollChanged += new ScrollChangedEventHandler(sv1_ScrollChanged);
        sv2.ScrollChanged += new ScrollChangedEventHandler(sv2_ScrollChanged);
    }

    void sv1_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        sv2.ScrollToVerticalOffset(sv1.VerticalOffset);
    }

    void sv2_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        sv1.ScrollToVerticalOffset(sv2.VerticalOffset);
    }
}

43-WPF-Datagrid列锁定

这节是利用了上节课的技巧

<Window x:Class="DataGridDemo.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:DataGridDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Column="0" x:Name="dataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Width="80" Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid Grid.Column="1" x:Name="dataGrid2" ItemsSource="{Binding}" AutoGenerateColumns="False" VerticalScrollBarVisibility="Hidden">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age}"/>
                <DataGridHyperlinkColumn Header="Email" Width="950" 
                                         Binding="{Binding Email}"/>
                <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age}"/>
                <DataGridHyperlinkColumn Header="Email" Width="950" 
                                         Binding="{Binding Email}"/>
                <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age}"/>
                <DataGridHyperlinkColumn Header="Email" Width="950" 
                                         Binding="{Binding Email}"/>
                <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age}"/>
                <DataGridHyperlinkColumn Header="Email" Width="950" 
                                         Binding="{Binding Email}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>Code language: HTML, XML (xml)

44-datagrid去掉左上角和左边行头

HeadersVisibility="Column"Code language: JavaScript (javascript)

去掉 左边行头

<DataGrid Grid.Column="1" x:Name="dataGrid2" ItemsSource="{Binding}" AutoGenerateColumns="False" VerticalScrollBarVisibility="Hidden"  HeadersVisibility="Column">
            <DataGrid.RowHeaderStyle>
                <Style TargetType="{x:Type DataGridRowHeader}">
                    <Setter Property="Visibility" Value="Hidden"/>
                    <Setter Property="Width" Value="0"/>
                </Style>
            </DataGrid.RowHeaderStyle>
            <DataGrid.Columns>Code language: HTML, XML (xml)

45-设置datagrid行高

<DataGrid.RowStyle>
                    <Style TargetType="DataGridRow">
                        <Setter Property="Height" Value="60" />
                    </Style>
                </DataGrid.RowStyle>Code language: HTML, XML (xml)
<DataGrid Grid.Column="0" x:Name="dataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden">
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Setter Property="Height" Value="60" />
                </Style>
            </DataGrid.RowStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Width="80" Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>Code language: HTML, XML (xml)

46-WPF 实现DataGrid行鼠标经过等等事件控制

WPF 实现DataGrid行鼠标经过、点击时的背景、文字、行高等样式

直接上代码

<DataGrid Grid.Column="1" x:Name="dataGrid2" ItemsSource="{Binding}" AutoGenerateColumns="False" VerticalScrollBarVisibility="Hidden"  HeadersVisibility="Column">
            <DataGrid.RowHeaderStyle>
                <Style TargetType="{x:Type DataGridRowHeader}">
                    <Setter Property="Visibility" Value="Hidden"/>
                    <Setter Property="Width" Value="0"/>
                </Style>
            </DataGrid.RowHeaderStyle>
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#FFF1FAFF"/>
                            <Setter Property="FontSize" Value=" 20"/>
                            <Setter Property="Height" Value="30"/>
                            <Setter Property="Foreground" Value="Blue"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.RowStyle>Code language: HTML, XML (xml)

47-WPF中Auto与星号的差别

WPF中Auto与*的差别

Auto 表示自己主动适应显示内容的宽度,如自己主动适应文本的宽度,文本有多长,控件就显示多长。

  • 则表示按比例来分配宽度。
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="7*" />Code language: HTML, XML (xml)

相同,行能够这样定义

<RowDefinition Height="3*" />
<RowDefinition Height="7*" />Code language: HTML, XML (xml)

这些数字能够是小数。如果数字缺省,则默认是1。

在这个样例中,列2的宽度是列1的1.5倍。

<ColumnDefinition Width="1.5*" />
<ColumnDefinition />Code language: HTML, XML (xml)

Auto和*能够混合使用。在这个样例中,后两行的宽度在前两行分配完之后,按比例获取剩余的宽度。

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />  <!-- Auto-fit to content, 'Hi' -->
    <ColumnDefinition Width="50.5" />  <!-- Fixed width: 50.5 device units) -->
    <ColumnDefinition Width="69*" />   <!-- Take 69% of remainder -->
    <ColumnDefinition Width="31*"/>    <!-- Take 31% of remainder -->
</Grid.ColumnDefinitions>
<TextBlock Text="Hi" Grid.Column="0" />Code language: HTML, XML (xml)

*我们可以理解为一份的意思。比如

<Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
    </Grid>Code language: HTML, XML (xml)

不写 本质上就是1*,比如上面 等价于

<Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
    </Grid>Code language: HTML, XML (xml)

Auto的意思是自动根据它的内容来决定,内容多大 它就多大。

*星号的行列 是最后分配的。首先让具体数据的列或者行 还有auto的行 分配后 剩下才分配。

所以我们的例子 就是先auto根据文本大小分了 然后再分配具体数字的最后一列。然后再剩下的 12 4三列就行按份分配。

<Window x:Class="WpfApplication4.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:WpfApplication4"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="50"/>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="2" Grid.Row="1">11111111111111111111111</TextBlock>
        <TextBlock Grid.Column="2" Grid.Row="3">22222</TextBlock>
    </Grid>
</Window>Code language: HTML, XML (xml)

48-绝对定位

我们使用画布来进行定位。画布的定位 可以通过设置 Left top right Bottom几个属性来控制 控件在画布中的位置。并且执行嵌套在其他控件中。比如我们可以让Canvas在Grid中的某个区域。

<Canvas Grid.Column="2" Margin="10,14,0,0">
                <TextBlock Canvas.Left="10" VerticalAlignment="Center">生产进度</TextBlock>
            </Canvas>Code language: HTML, XML (xml)

有点类似我们以前的winform项目的布局。

当四个属性都配置的话,那么WPF里面 默认以Left和Top为准。

<TextBlock Background="Green" Canvas.Left="60" Canvas.Top="100"  
        Canvas.Right="90" Canvas.Bottom="160" VerticalAlignment="Center">
        FoxDevelop</TextBlock>Code language: HTML, XML (xml)

49-WPF之自定义ToolTip样式和模板

WPF之自定义ToolTip样式和模板

<Window x:Class="WpfApplication4.ToolTipCustom"
        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:WpfApplication4"
        mc:Ignorable="d"
        Title="ToolTipCustom" Height="300" Width="300">
    <Window.Resources>
        <Style TargetType="{x:Type ToolTip}">
            <Setter Property="Foreground" Value="White"/>
            <Setter Property = "HorizontalOffset" Value="10"/>
            <Setter Property = "VerticalOffset" Value="10"/>
            <Setter Property = "Background" Value="MediumBlue"/>
            <Setter Property = "FontSize" Value="18"/>
            <Setter Property="BorderBrush" Value="White"/>
        </Style>
    </Window.Resources>
    
    <Grid>
        <TextBlock ToolTip="www.FoxDevelop" Width="100" Height="50" Background="Red">
            FoxDevelop
        </TextBlock>
    </Grid>
</Window>Code language: HTML, XML (xml)

50-WPF中的Binding技巧

我们来看一看ElementName、Source、RelativeSource 三种绑定的方式

  1. ElementName顾名思义就是根据Ui元素的Name来进行绑定:
<Window x:Class="WpfApplication4.BindingDemo"
        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:WpfApplication4"
        mc:Ignorable="d"
        x:Name="myWin"
        Background="Green"
        Title="BindingDemo" Height="300" Width="300">
    <Grid Background="White">
        <Button Width="150" Height="100" Content="FoxDevelop" Background="{Binding ElementName=myWin, Path=Background}"/>
    </Grid>
</Window>Code language: HTML, XML (xml)

效果等同于

<Window>
    <Grid>
        <Button Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window},Path=Background}"/>
    </Grid>
</Window>Code language: HTML, XML (xml)

区别:ElementName属性用于引用一个UI对象的名称,其作用域在同一XAML文件内,不能引用另一XAML文件的某个Ui元素名。

  1. Source属性用于指定对象绑定路径的引用。其特点是:Source属性通常用于绑定设置的对象时,是已知的。
<Window x:Class="WpfApplication4.BindingDemo"
        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:WpfApplication4"
        mc:Ignorable="d"
        x:Name="myWin"
        Background="White"
        Title="BindingDemo" Height="300" Width="300">
    <Window.Resources>
        <Style x:Key="ButtonStyle" TargetType="Button">
            <Setter Property="Foreground" Value="Blue"/>
            <Setter Property = "Background" Value="Green"/>
            <Setter Property = "FontSize" Value="18"/>
            <Setter Property="BorderBrush" Value="White"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Button Width="150" Height="50" Content="FoxDevelop" Style="{Binding Source={StaticResource ResourceKey=ButtonStyle}}"/>
    </Grid>
</Window>Code language: HTML, XML (xml)
  1. RelativeSource

在不确定绑定的Source时,但知道与绑定对象两者相对关系时就需要使用RelativeSource,这也是RelativeSource 与ElementName和Source的最大区别。

RelativeSource 的三种典型用法:

  1. UI元素的一个属性绑定在自身的另一个属性上
<Window x:Class="WpfApplication4.BindingDemo"
        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:WpfApplication4"
        mc:Ignorable="d"
        x:Name="myWin"
        Background="White"
        Title="BindingDemo" Height="300" Width="300">
    <Grid>
        <Label Width="150" Height="50" Content="www.FoxDevelop" BorderBrush="Red" Background="{Binding Path=BorderBrush, RelativeSource={RelativeSource Self}}"/>
    </Grid>
</Window>Code language: HTML, XML (xml)
  1. UI元素的一个属性绑定在某个父元素的属性上
<Window x:Class="WpfApplication4.BindingDemo"
        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:WpfApplication4"
        mc:Ignorable="d"
        x:Name="myWin"
        Background="White"
        Title="BindingDemo" Height="300" Width="300">
    <Grid Background="Green">
        <Label Width="150" Background="Blue" Height="50" Content="www.FoxDevelop" Foreground="{Binding Path=Background, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}"/>
    </Grid>
</Window>Code language: HTML, XML (xml)
  1. Template中的元素的属性绑定在Template使用者元素的属性上
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}

例子:

<Style TargetType="{x:Type local:NumericUpDown}">
  <Setter Property="HorizontalAlignment" Value="Center"/>
  <Setter Property="VerticalAlignment" Value="Center"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type local:NumericUpDown}">
        <Grid Margin="3">
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
          </Grid.ColumnDefinitions>
          <Border BorderThickness="1" BorderBrush="Gray"
                  Margin="2" Grid.RowSpan="2"
                  VerticalAlignment="Center" HorizontalAlignment="Stretch">
            <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value}"
                       Width="60" TextAlignment="Right" Padding="5"/>
          </Border>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>Code language: HTML, XML (xml)

利用TemplateBinding 绑定模板与原对象之间的属性

{TemplateBinding Path=PathToProperty}

例子:

<ControlTemplate TargetType="{x:Type Button}" x:Key="buttonTemp">                        
    <Border BorderThickness="3" Background="{TemplateBinding Foreground}">                  
        <TextBlock Foreground="{TemplateBinding Background}"/>                    
    </Border>                       
</ControlTemplate>Code language: HTML, XML (xml)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注