首页 > 其他分享 >WPF初学习(一)

WPF初学习(一)

时间:2024-06-05 17:23:53浏览次数:26  
标签:控件 绑定 学习 Add new WPF 模板 属性

控件模板

控件模板又包括ControlTemplate和ItemsPanelTemplate

ControlTemplate(控件模板)不仅是用于来定义控件的外观、样式, 还可通过控件模板的触发器(ControlTemplate.Triggers)修改控件的行为、响应动画等。

样式定义了一些基础的样式, 背景颜色、字体颜色、边框大小、垂直水平位置等, 除此之外, 下方则有一个Template的对象, 其中则就是ControlTemplate, 可以看到, ControlTemplate定义了一个Border ,然后其中定义了一个内弄呈现的控件, ContentPresenter则主要用于呈现按钮的显示内容主体。

ControlTemplate中的TemplateBinding 的作用

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

<Button>
    <Button.Template>
        <ControlTemplate>
            <!--定义视觉树-->
            <Grid>
                <Ellipse Name="faceEllipse"
                         Width="{TemplateBinding Button.Width}" 
                         Height="{TemplateBinding Control.Height}"  
                         Fill="{TemplateBinding Button.Background}"/>
                <TextBlock Name="txtBlock" 
                           Margin="{TemplateBinding Button.Padding}"                                      VerticalAlignment="Center" 
                           HorizontalAlignment="Center" 
                           Text="{TemplateBinding Button.Content}"/>
            </Grid>
            <!--定义视觉树_end-->            
        </ControlTemplate>
    </Button.Template>
</Button>

在上面的代码中,我们修改了Button的Template属性,我们定义了一个ControlTemplate,在 < ControlTemplate > ... 之间包含的是模板的视觉树,也就是如何显示控件的外观,我们这里使用了一个Ellipse(椭圆)和一个TextBlock(文本块)来定义控件的外观。
很容易联想到一个问题:控件(Button)的一些属性,比如高度、宽度、文本等如何在新定义的外观中表现出来呢?
我们使用TemplateBinding 将控件的属性与新外观中的元素的属性关联起来Width="{TemplateBinding Button.Width}" ,这样我们就使得椭圆的宽度与按钮的宽度绑定在一起而保持一致,同理我们使用Text="{TemplateBinding Button.Content}"将TextBlock的文本与按钮的Content属性绑定在一起。

除了定义控件的默认外观外,也许我们想还定义当外界刺激我们的控件时,控件外观做出相应的变化,这是我们需要触发器。

<Button Content="test btn" Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="1" Grid.RowSpan="1"  >
        <Button.Template>
          <ControlTemplate>
            <!--定义视觉树-->
            <Grid>
              <Ellipse Name="faceEllipse" 
                       Width="{TemplateBinding Button.Width}" 
                       Height="{TemplateBinding Control.Height}" 
                       Fill="{TemplateBinding Button.Background}"/>
              <TextBlock Name="txtBlock"
                         Margin="{TemplateBinding Button.Padding}"    			                     VerticalAlignment="Center"  
                         HorizontalAlignment="Center" 
                         Text="{TemplateBinding Button.Content}" />
            </Grid>
            <!--定义视觉树_end-->
            <!--定义触发器-->
            <ControlTemplate.Triggers>
              <Trigger  Property="Button.IsMouseOver"  Value="True">
                <Setter Property="Button.Foreground" Value="Red" />             
              </Trigger>
            </ControlTemplate.Triggers>
            <!--定义触发器_End-->
          </ControlTemplate>
        </Button.Template>
      </Button>

在上面的代码中注意到 < ControlTemplate .Triggers >... </ControlTemplate.Triggers>之间的部分,我们定义了触发器 ,其表示当我们Button的IsMouseIOver属性变成True时,将使用设置器 来将Button的Foreground属性设置为Red。这里有一个隐含的意思是:当Button的IsMouseIOver属性变成False时,设置器中设置的属性将回复原值。

如果需要宠用模板,只要把它定义为资源

<Window.Resources>
    <ControlTemplate TargetType="Button" x:Key="ButtonTemplate">
        <!--定义视觉树-->
        <Grid>
          <Ellipse Name="faceEllipse" 
                   Width="{TemplateBinding Button.Width}" 
                   Height="{TemplateBinding Control.Height}"  
                   Fill="{TemplateBinding Button.Background}"/>
          <TextBlock Name="txtBlock" 
                     Margin="{TemplateBinding Button.Padding}" 
                     VerticalAlignment="Center" 
                     HorizontalAlignment="Center"  
                     Text="{TemplateBinding Button.Content}" />
        </Grid>
        <!--定义视觉树_end-->
        <!--定义触发器-->
        <ControlTemplate.Triggers>
          <Trigger  Property="Button.IsMouseOver"  Value="True">
            <Setter Property="Button.Foreground" Value="Red" />
          </Trigger>
        </ControlTemplate.Triggers>
        <!--定义触发器_End--> 
    </ControlTemplate>
  </Window.Resources>

上面的代码将我们原来的模板定义为窗体范围内的资源,其中 TargetType ="Button"指示我们的模板作用对象为Button,这样在整个窗体范围内的按钮都可以使用这个模板了,模板的使用方法也很简单。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ControlTemplateTest" Height="300" Width="300"
    >
 
  <Window.Resources>
    <ControlTemplate TargetType="Button" x:Key="ButtonTemplate">
        <!--定义视觉树-->
        <Grid>
          <Ellipse Name="faceEllipse" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}"  Fill="{TemplateBinding Button.Background}"/>
          <TextBlock Name="txtBlock" Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center"  HorizontalAlignment="Center"  Text="{TemplateBinding Button.Content}" />
        </Grid>
        <!--定义视觉树_end-->
        <!--定义触发器-->
        <ControlTemplate.Triggers>
          <Trigger  Property="Button.IsMouseOver"  Value="True">
            <Setter Property="Button.Foreground" Value="Red" />
          </Trigger>
        </ControlTemplate.Triggers>
        <!--定义触发器_End--> 
    </ControlTemplate>
  </Window.Resources>
  
  
    <Grid ShowGridLines="True">
      
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.2*"/>
        <ColumnDefinition Width="0.6*"/>
        <ColumnDefinition Width="0.2*"/>
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="0.3*"/>
        <RowDefinition Height="0.3*"/>
        <RowDefinition Height="0.4*"/>
      </Grid.RowDefinitions>
 
      <Button Content="test btn1" 
              Grid.Column="0"
              Grid.ColumnSpan="1" 
              Grid.Row="0" 
              Grid.RowSpan="1"  />
      <Button Content="test btn2"
              Grid.Column="1"
              Grid.ColumnSpan="1"
              Grid.Row="1" 
              Grid.RowSpan="1"  
              Template="{StaticResource ButtonTemplate}" />
      <Button Content="test btn2"
              Grid.Column="2" 
              Grid.ColumnSpan="1" 
              Grid.Row="2"
              Grid.RowSpan="1" 
              Template="{StaticResource ButtonTemplate}" />
    </Grid>
</Window>

如果想加入一些动画效果的话,可以在触发器中,调用一个故事板来达到对事件响应时的动画效果

<EventTrigger RoutedEvent="Mouse.MouseDown" SourceName="faceEllipse">
    <EventTrigger.Actions>
        <BeginStoryboard Storyboard="{StaticResource MouseClickButtonStoryboard}"/>
    </EventTrigger.Actions>    
</EventTrigger>
<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ControlTemplateTest" Height="300" Width="300"
    >
 
  <Window.Resources>
    <ControlTemplate TargetType="Button" x:Key="ButtonTemplate">
      <!--定义视觉树-->
      <Grid>
        <Ellipse Name="faceEllipse" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}"  Fill="{TemplateBinding Button.Background}"/>
        <TextBlock Name="txtBlock" Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center"  HorizontalAlignment="Center"  Text="{TemplateBinding Button.Content}" />
      </Grid>
      <!--定义视觉树_end-->
 
      <!--定义动画资源-->
      <ControlTemplate.Resources>
        <Storyboard x:Key="MouseClickButtonStoryboard">
          <DoubleAnimationUsingKeyFrames Storyboard.TargetName="faceEllipse" Storyboard.TargetProperty="Width" BeginTime="00:00:00">
            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="50"/>
            <SplineDoubleKeyFrame KeyTime="00:00:00.3" Value="100"/>
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </ControlTemplate.Resources>
      <!--定义动画资源_end-->
 
      <!--定义触发器-->
      <ControlTemplate.Triggers>
        <Trigger  Property="Button.IsMouseOver"  Value="True">
          <Setter Property="Button.Foreground" Value="Red" />
        </Trigger>
        <EventTrigger RoutedEvent="Mouse.MouseDown" SourceName="faceEllipse">
          <EventTrigger.Actions>
            <BeginStoryboard Storyboard="{StaticResource MouseClickButtonStoryboard}"/>
          </EventTrigger.Actions>    
        </EventTrigger>
        <EventTrigger RoutedEvent="Mouse.MouseDown" SourceName="txtBlock">
          <EventTrigger.Actions>
            <BeginStoryboard Storyboard="{StaticResource MouseClickButtonStoryboard}"/>
          </EventTrigger.Actions>
        </EventTrigger>
      </ControlTemplate.Triggers>
      <!--定义触发器_End-->
      
    </ControlTemplate>
 
 
   
  </Window.Resources>
  
  
    <Grid ShowGridLines="True">
      
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.2*"/>
        <ColumnDefinition Width="0.6*"/>
        <ColumnDefinition Width="0.2*"/>
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="0.3*"/>
        <RowDefinition Height="0.3*"/>
        <RowDefinition Height="0.4*"/>
      </Grid.RowDefinitions>
 
      <Button Content="test btn1" 
              Grid.Column="0" 
              Grid.ColumnSpan="1"
              Grid.Row="0"
              Grid.RowSpan="1"  />
      <Button Content="test btn2" 
              Grid.Column="1"
              Grid.ColumnSpan="1"
              Grid.Row="1" 
              Grid.RowSpan="1"  
              Template="{StaticResource ButtonTemplate}" />
      <Button Content="test btn2"
              Grid.Column="2" 
              Grid.ColumnSpan="1"
              Grid.Row="2"
              Grid.RowSpan="1"  
              Template="{StaticResource ButtonTemplate}" />
    </Grid>
</Window>
 
 

mageButton自定义控件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 SoftRGB.Controls
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:SoftRGB.Controls"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:SoftRGB.Controls;assembly=SoftRGB.Controls"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
    /// 并重新生成以避免编译错误:
    ///
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:ImageButton/>
    ///
    /// </summary>
    public class ImageButton : Button
    {
        static ImageButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
        }
 
        #region 依赖属性
 
        public static readonly DependencyProperty NormalImageProperty =
            DependencyProperty.Register("NormalImage", typeof(string), typeof(ImageButton), null);
        public static readonly DependencyProperty OverImageProperty =
           DependencyProperty.Register("OverImage", typeof(string), typeof(ImageButton), null);
        public static readonly DependencyProperty PressedImageProperty =
           DependencyProperty.Register("PressedImage", typeof(string), typeof(ImageButton), null);
        public static readonly DependencyProperty DisableImageProperty =
           DependencyProperty.Register("DisableImage", typeof(string), typeof(ImageButton), null);
 
        #endregion
 
        #region 属性
 
        /// <summary>
        /// 正常状态下显示的图片
        /// </summary>
        public string NormalImage
        {
            get { return (string)GetValue(NormalImageProperty); }
            set { SetValue(NormalImageProperty, value); }
        }
 
        /// <summary>
        /// 鼠标滑过状态下显示的图片
        /// </summary>
        public string OverImage
        {
            get { return (string)GetValue(OverImageProperty); }
            set { SetValue(OverImageProperty, value); }
        }
 
        /// <summary>
        /// 鼠标点击状态下显示的图片
        /// </summary>
        public string PressedImage
        {
            get { return (string)GetValue(PressedImageProperty); }
            set { SetValue(PressedImageProperty, value); }
        }
 
        /// <summary>
        /// 禁用状态下显示的图片
        /// </summary>
        public string DisableImage
        {
            get { return (string)GetValue(DisableImageProperty); }
            set { SetValue(DisableImageProperty, value); }
        }
 
        #endregion
 
    }
}
<Style TargetType="{x:Type local:ImageButton}">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ImageButton}">
                <Grid x:Name="Root" Background="Transparent">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalUI" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{StaticResource Visible}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverUI" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Visible}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PressedUI" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Visible}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableUI" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Visible}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Image x:Name="NormalUI" Source="{Binding NormalImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/>
                            <Image x:Name="OverUI" Source="{Binding OverImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/>
                            <Image x:Name="PressedUI" Source="{Binding PressedImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/>
                            <Image x:Name="DisableUI" Source="{Binding DisableImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/>
                            <ContentPresenter x:Name="ContentPresenter" Margin="{TemplateBinding Padding}" ContentTemplate="{TemplateBinding ContentTemplate}"
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                        </Grid>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

数据模板

数据模板是一段如何显示绑定在VM对象的XAML代码。数据模板可以包含任意元素的组合,基于Binding来显示不同的信息。

在实际的开发中数据模板的应用场景很多,同样一个控件可以根据不同的绑定源,根据以设置好的数据模板可以显示对应的不同的内容。

img

  • 1.Grid这种列表表格中修改Cell的数据格式, CellTemplate可以修改单元格的展示数据的方式。
  • 2.针对列表类型的控件, 例如树形控件,下拉列表,列表控件, 可以修改其中的ItemTemplate。
  • 3.修改ContentTemplate, 例UserControl控件的数据展现形式。

CellTemplate 模板

实现一个DataGrid 展示一个普通的数据标, 同时新增一列CellTemplate添加两个自定义的按钮

            <DataGrid Name="gd" AutoGenerateColumns="False" CanUserSortColumns="True"  CanUserAddRows="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding UserName}" Width="100" Header="学生姓名"/>
                    <DataGridTextColumn Binding="{Binding ClassName}" Width="100" Header="班级名称"/>
                    <DataGridTextColumn Binding="{Binding Address}" Width="200" Header="地址"/>
                    <DataGridTemplateColumn Header="操作" Width="100" >
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
                                    <Button Content="编辑"/>
                                    <Button Margin="8 0 0 0" Content="删除" />
                                </StackPanel>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>


完成操作, 然后后台进行该DataGrid进行绑定数据, 查询绑定后的效果。

            List<Student> students = new List<Student>();
            students.Add(new Student() { UserName = "小王", ClassName = "高二三班", Address = "广州市" });
            students.Add(new Student() { UserName = "小李", ClassName = "高三六班", Address = "清远市" });
            students.Add(new Student() { UserName = "小张", ClassName = "高一一班", Address = "深圳市" });
            students.Add(new Student() { UserName = "小黑", ClassName = "高一三班", Address = "赣州市" });
            gd.ItemsSource = students;

最终的效果, 在数据的表格最后一列, 将会在一列中分别生成 两个普通按钮。

img

ItemTemplate

在列表的控件中, 常常会出现一些需求, 类似在下拉控件或树控件中添加一个 CheckBox选择框, 一个图标或图片, 这个时候, 我们就可以利用自定义的DataTemplate 来实现这个功能,
接下来, 用一个示例来简单演示其功能, 同样, 该例子演示利用 ListBox 和 ComboBox来绑定一个 颜色代码列表, 同时展示其颜色。

    <Window.Resources>
        <DataTemplate x:Key="comTemplate">
            <StackPanel Orientation="Horizontal" Margin="5,0">
                <Border Width="10" Height="10" Background="{Binding Code}"/>
                <TextBlock Text="{Binding Code}" Margin="5,0"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <ComboBox Name="cob" Width="120" Height="30" ItemTemplate="{StaticResource comTemplate}"/>
            <ListBox Name="lib" Width="120" Height="100" Margin="5,0"  ItemTemplate="{StaticResource comTemplate}"/>
        </StackPanel>
    </Grid>

上面的代码中, 定义了一个DataTemplate , 顶一个 长宽10px的border用于显示颜色代码, 绑定到Border背景颜色上, 定义了一个TextBlock用于展示颜色的代码。

            List<Color> ColorList = new List<Color>();
            ColorList.Add(new Color() { Code = "#FF8C00" });
            ColorList.Add(new Color() { Code = "#FF7F50" });
            ColorList.Add(new Color() { Code = "#FF6EB4" });
            ColorList.Add(new Color() { Code = "#FF4500" });
            ColorList.Add(new Color() { Code = "#FF3030" });
            ColorList.Add(new Color() { Code = "#CD5B45" });

            cob.ItemsSource = ColorList;
            lib.ItemsSource = ColorList;

ItemsControl

定义ItemsControl 主要分两个步骤:

1.设置ItemsPanel容器, 用于容纳列表的最外层容器

2.定义子项的DataTemplate

           <ItemsControl Name="ic">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Width="50" Height="50" Content="{Binding Code}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

上面代码中, 定义了一个WarpPanel 容器为ItemControl的 最外层容器, 子项数据模板则绑定了一个按钮, 后台代码绑定几条数据, 查看其效果: 横排排列五个按钮, 内容分别是 1~6.

            List<Test> tests = new List<Test>();
            tests.Add(new Test() { Code = "1" });
            tests.Add(new Test() { Code = "2" });
            tests.Add(new Test() { Code = "3" });
            tests.Add(new Test() { Code = "4" });
            tests.Add(new Test() { Code = "6" });
            ic.ItemsSource = tests;

img

绑定

在winform中, 我们常常会用到各种类型的赋值, 例如:

  • button1.Text="Hello";
  • label.Text="Hello";
  • ...

类似这种赋值操作, 我们之所以不称之为绑定, 主要原因是因为他们大多数操作都是一次性的, 无论是数据还是按钮本身发生变化,对两者而言都是不可见的。
而绑定的概念则侧重于: 两者的关联,协议与两者之间的影响。

img

  • Text=
    • {Binding }: Binding的声明语法, 一对尖括号,开头声明以Binding 开始。
    • ElementName= : 该声明意为, 设置元素的名称
    • Path: 设置关联元素的位置,上例中设置为元素的value属性。

在WPF中绑定的模式又分为五种:

1.OneWay(单向绑定) : 当源属性发生变化更新目标属性, 类似上面的例子中, 滑动变化更新文本的数据。

2.TwoWay(双向绑定) : 当源属性发生变化更新目标属性, 目标属性发生变化也更新源属性。

与单向绑定的区别可以理解为, 前者只能打你,被打者不能还手, 双向绑定的意思则是: 你敢打我一巴掌,我也能回你一巴掌

3.OneTime(单次模式) : 根据第一次源属性设置目标属性, 在此之后所有改变都无效。

如第一次绑定了数据源为0, 那么无论后面如何改变 2、3、4... 都无法更新到目标属性上。

4.OneWayToSource : 和OneWay类型, 只不过整个过程倒置。

5.Default : 既可以是双向,也可以是单项, 除非明确表明某种模式, 否则采用该默认绑定

绑定到非元素上

https://docs.microsoft.com/zh-cn/?WT.mc_id=DT-MVP-5003986
微软开发者平台:
https://developer.microsoft.com/en-us/?WT.mc_id=DT-MVP-5003986

什么是绑定(Binding)?

在winform中, 我们常常会用到各种类型的赋值, 例如:

  • button1.Text="Hello";
  • label.Text="Hello";
  • ...

类似这种赋值操作, 我们之所以不称之为绑定, 主要原因是因为他们大多数操作都是一次性的, 无论是数据还是按钮本身发生变化,对两者而言都是不可见的。
而绑定的概念则侧重于: 两者的关联,协议与两者之间的影响。
首先, 从一个简单的例子来理解什么是绑定。

  • 创建一个滑块控件, 并且希望在滑动的过程中, 把值更新到另外一个静态文本上。代码如下:
    img

在winform中, 我们常规的做法会给滑块创建一个值改变事件,同时将滑块的值赋值给文本。
接下来, 我只需要在静态文本中添加一小段绑定的声明,即可完整原本很复杂的操作:

  • Text=
    • {Binding }: Binding的声明语法, 一对尖括号,开头声明以Binding 开始。
    • ElementName= : 该声明意为, 设置元素的名称
    • Path: 设置关联元素的位置,上例中设置为元素的value属性。

那么该如何理解整句话的意义, 翻译: 静态文本TextBlock的Text属性将通过绑定的方式关联到元素名'slider'的value属性上。
img

效果图所示:
img
可以看到,在滑块不断的滑动过程中, TextBlock也在不断的发生变化, 说明TextBlock已经得到了滑动滑动过程中的值变化, 这种关联, 我们称之为绑定, 在WPF当中, 绑定又分很多种, 而上面这种则是通过元素绑定的方式。
理解了基础的绑定之后,然后就是理解绑定的模式。

绑定的模式就类似我们商业中的合作, 是一次性回报还是持续获益, 是否可以单方面终止, 是否具有投票权等, 在WPF中绑定的模式又分为五种:

  • OneWay(单向绑定) : 当源属性发生变化更新目标属性, 类似上面的例子中, 滑动变化更新文本的数据。示例:
    img
    效果:
    img
  • TwoWay(双向绑定) : 当源属性发生变化更新目标属性, 目标属性发生变化也更新源属性。
    • 与单向绑定的区别可以理解为, 前者只能打你,被打者不能还手, 双向绑定的意思则是: 你敢打我一巴掌,我也能回你一巴掌。示例:
      img
      效果:
      img
  • OneTime(单次模式) : 根据第一次源属性设置目标属性, 在此之后所有改变都无效。
    • 如第一次绑定了数据源为0, 那么无论后面如何改变 2、3、4... 都无法更新到目标属性上。示例:
      img
      效果:
      img
  • OneWayToSource : 和OneWay类型, 只不过整个过程倒置。示例:
    img
    效果:
    img
  • Default : 既可以是双向,也可以是单项, 除非明确表明某种模式, 否则采用该默认绑定

标签:控件,绑定,学习,Add,new,WPF,模板,属性
From: https://www.cnblogs.com/guan-tou6/p/18233406

相关文章

  • 跟着杨中科学习(二)日志
    日志系统日志级别Trace<Debug<Information<Warning<Error<Critical输出到控制台NugetMicrosoft.Extensions.LoggingMicrosoft.Extensions.Logging.ConsoleDI注入services.AddLogging(logBuilder=>{ logBuilder.AddConsole();//可多个ProciderlogBuilder.SetMini......
  • 关于Android的学习心得
    一、AS中的主要组件1、Activity组件[1]-Activity的基本使用1.Activity是什么Activity是一种可以包含用户界面的组件,主要用于和用户进行交互。一个应用程序中可以包含零个或多个Activity。2.Activity中的onCreate()方法onCreate()方法:用于在活动(Activity)的生命周期中进行......
  • WPF界面反编译神器Snoop使用介绍
    Snoop介绍Snoop是一款开源的WPF监视工具,它能够监视或浏览任何正在运行的WPF应用程序的可视化、逻辑和自动化树(无需调试器),还可以更改属性值、查看触发器、在属性更改时设置断点等。项目地址:https://github.com/snoopwpf/snoopwpf 运行可以到githubrelease下载已经编译......
  • 监督学习
    一.线性回归算法监督学习算法是机器学习领域中的一个重要分支,其核心思想是通过已知的输入和输出数据样本(通常被称为训练数据集)来学习一个模型(也称为学习器),然后利用这个模型对未知的数据进行预测或分类。下面是对监督学习算法的更详细解释:1.基本概念:监督学习算法是建立在有标记......
  • 正则表达式学习(3)——语法
    普通字符[abc]匹配中括号的所有字符[^abc]匹配除了中括号的所有字符[A-Z]匹配A-Z的大写字母区间内的字符[a-z]匹配a-z的小写字母区间内的字符[0-9]匹配0-9的数字.匹配除了换行、回车(\n,\r)的单个字符,等价于[^\n\r]\s是匹配所有空白符,包括换行\S非空白符,不包括换......
  • C++学习笔记(8):指针
      指针的作用:指针保存数据的地址,可以通过指针间接访问内存。1.指针的定义和使用指针的定义语法:数据类型*指针变量名使用:*指针变量名,通过*操作指针指向内存,可以对内存中的数据进行访问和读写。示例:#include<iostream>usingnamespacestd;intmain(){ inta=......
  • python基础学习day2
    python基础1、注释#单行注释'''三单引号注释'''"""三双引号多行注释"""2、数据类型一、整型(int)表示人的年龄、号码等age=18#age=int(18)print(id(age))print(type(age))print(age)二、浮点型(float)表示身高、体重、薪资salary=2.1#sala......
  • Python深度学习实践:自动编码器在数据降维中的应用
    Python深度学习实践:自动编码器在数据降维中的应用1.背景介绍在现代数据科学和机器学习领域中,高维数据处理是一个常见的挑战。许多真实世界的数据集包含大量的特征,这些特征往往存在高度的冗余和噪声。高维数据不仅增加了计算复杂性,还容易导致维数灾难(curseofdimensio......
  • 正则表达式学习(2)---字符特性
    正则表达式特性字符匹配普通字符:匹配字面值。元字符:元字符具有特殊的含义,例如\d匹配任意数字字符,\w匹配任意字母数字字符,.匹配任意字符(除了换行符)等。量词*:匹配前面的模式零次或多次,例如aa*+:匹配前面的模式一次或多次,例如aa+?:匹配前面的模式零次或一次,例如aa?......
  • Docker部署深度学习模型
    Docker部署深度学习模型基础概念DockerDocker是一个打包、分发和运行应用程序的平台,允许将你的应用程序和应用程序所依赖的整个环境打包在一起。比如我有一个目标检测的项目,我想分享给朋友,那么他首先需要在自己的电脑上配置好显卡驱动、CUDA、CuDNN,在拿到我的项目后,还需要安......