WPF初学习(一)

news/2025/3/17 9:31:27/文章来源:https://www.cnblogs.com/guan-tou6/p/18233406

控件模板

控件模板又包括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,这样在整个窗体范围内的按钮都可以使用这个模板了,模板的使用方法也很简单。

<Windowxmlns="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(单向绑定) : 当源属性发生变化更新目标属性, 类似上面的例子中, 滑动变化更新文本的数据。

image-20240307153200576

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

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

image-20240307153220474

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

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

image-20240307153301399

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

image-20240307153335118

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 : 既可以是双向,也可以是单项, 除非明确表明某种模式, 否则采用该默认绑定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/720413.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文搞懂Kafka,在项目里面更加得心应手的使用

1. kafka关键概念与术语 1.1 简单的例子说明kafka的使用场景 Apache kafka 是消息中间件的一种,我发现很多人不知道消息中间件是什么,在开始学习之前,我这边就先简单的解释一下什么是消息中间件,只是粗略的讲解,目前kafka已经可以做更多的事情。 举个例子:生产者消费者,…

回归模型的算法性能评价

一、概述 在一般形式的回归问题中,会得到系列的预测值,它们与真实值(ground truth)的比较表征了模型的预测能力,为有效量化这种能力,常见的性能评价指标有可解释方差(EVS)、平均绝对误差(MAE)、均方误差(MSE)、均方根误差(RMSE)、决定系数(R2)等。值得一提的是…

还在拼冗长的WhereIf吗?100行代码解放这个操作

通常我们在做一些数据过滤的操作的时候,经常需要做一些判断再进行是否要对其进行条件过滤。普通做法 最原始的做法我们是先通过If()判断是否需要进行数据过滤,然后再对数据源使用Where来过滤数据。 示例如下: if(!string.IsNullOrWhiteSpace(str)) {query = query.Where(a =…

“粘土风格”轻松拿捏,基于函数计算部署 ComfyUI实现AI生图

阿里云函数计算 FC 一键部署火爆全球工作流 AI 生图平台—— ComfyUI ,实现更高质量的图像生成,三步轻松完成“黏土”创意AI画作,晒图赢眼部按摩器等好礼! 活动地址:https://developer.aliyun.com/topic/june/fc?spm=a2c6h.29234099.J_6985717350.4.65997562KE82EH实验准…

医保“视界”大革新:可视化管理系统重塑就医体验

想象一下,在繁忙的医院里,患者和家属不再需要为了查询医保信息而四处奔波,也不再需要为了报销费用而焦头烂额。智慧医保可视化管理系统通过大数据、云计算等先进技术,将医保信息整合到一个平台上,实现了信息的实时更新和可视化展示在数字化浪潮席卷全球的今天,我们的生活…

数据安全之一 加解密介绍

一、场景信息系统不断发展,要求对于其中的数据安全性必须增加保护机制,否则数据泄露将会给企业带来不可估量的损失。基于此,数据的安全包括如下: 1)数据存储的安全存储包括:文件存储(包括含有敏感信息的图片)、数据库中的敏感数据的存储(比如:密码)、配置文件中的敏…

stm32系列--同一定时器双通道捕获

void TIM3_Cap_Init(u16 arr,u16 psc)//定时器3通道2输入捕获配置 {TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Pe…

赛博斗地主——使用大语言模型扮演Agent智能体玩牌类游戏。

通过大模型来实现多个智能体进行游戏对局这个想对已经比较成熟了无论是去年惊艳的斯坦福小镇还是比如metaGPT或者类似的框架都是使用智能体技术让大模型来操控,从而让大模型跳出自身“预测下一个token”的文字功能去探索更多的应用落地可能性。不过一直没有真正操作过,直到前…

Ollama,在centos7宿主机上,curl http://宿主机IP:11434 提示拒绝访问 ,但是curl http://localhost:11434 正常

Ollama,在centos7宿主机上,curl http://宿主机IP:11434 提示拒绝访问 ,但是curl http://localhost:11434 正常1.使用 netstat 或 ss 命令在宿主机上检查 11434 端口的状态[root@localhost ~]# netstat -tulnp | grep 11434 tcp 0 0 127.0.0.1:11434 0.…

NFS,smb和数据库文件

nfs的搭建网上有很多,可自行查看 Windows Server2012 R2搭建NFS服务器 - 知乎 (zhihu.com) 其中Windows10家庭版不支持NFS客户端,目前Windows上的协议是V3版本,防火墙上有NFS的选项,端口2049udp和tcp 在客户端上的访问和smb一样,都可映射网络驱动器,使用\\ip\目录方式访问…

JavaDoc生成文档

javaDoc命令是用来生成自己API文档的参数信息:@auchor:作者名 @version:版本号 @since:指明需要最早使用的jdk版本 @param:参数名 @return:返回值情况 @throws:异常抛出情况//主要生成的参数 如:/*** @author 林伟填* @version 1.0* @since 1.8*/public class doc {Str…

心诺安 x TapData:快速搭建云中数仓,助力电商企业实施“以用户为中心的”精细化运营

电商企业如何充分整合并利用自身数据资源,实现高效的数据管理和业务流程优化,迎接用户导向的电商精细化运营时代的挑战。使用 TapData,化繁为简,摆脱手动搭建、维护数据管道的诸多烦扰,轻量代替 OGG、DSG 等同步工具,「CDC + 流处理 + 数据集成」组合拳,加速仓内数据流转…