概述

UWP Community Toolkit Extensions 中有一个为FrameworkElement 提供的扩展 - FrameworkElement Extensions,本篇我们结合代码详细讲解 FrameworkElement Extensions 的实现。

FrameworkElement Extensions 为 FrameworkElement 提供了一种简单的绑定实际尺寸的方式,扩展利用 EnableActualSizeBinding 来指定是否允许实时绑定实际尺寸中的 ActualWidth 和 ActualHeight。 接下来看看官方示例的截图:

Source: https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI/Extensions/FrameworkElement

Doc: https://docs.microsoft.com/zh-cn/windows/uwpcommunitytoolkit/extensions/frameworkelementextensions

Namespace: Microsoft.Toolkit.Uwp.UI.Extensions; Nuget: Microsoft.Toolkit.Uwp.UI;

开发过程

代码分析

FrameworkElement Extensions 的功能实现比较简单,在 FrameworkElementExtensions.cs 类中;先看一下类的结构:

我们看到,类中定义了三个依赖属性:

  • EnableActualSizeBindingProperty - boolean,标志是否允许实际尺寸绑定;属性改变时触发 OnEnableActualSizeBindingtPropertyChanged;
  • ActualHeightProperty - double,实际尺寸的高度; 默认值 double.NaN;
  • ActualWidthProperty - double,实际尺寸的宽度;默认值 double.NaN;

而这三个依赖属性分别对应的 get 和 set 方法分别是:

  • GetEnableActualSizeBinding(obj) 和 SetEnableActualSizeBinding(obj, value)
  • GetActualHeight(obj) 和 SetActualHeight(obj, value)
  • GetActualWidth(obj) 和 SetActualWidth(obj, value)

下面看一下实际绑定和 EnableActualSizeBinding 的处理代码:

在 OnEnableActualSizeBindingtPropertyChanged(sender, args) 方法处理中,可以看到当 EnableActualSizeBinding 变为 True 时,强制刷新一次实际尺寸,且开始响应 SizeChanged 事件,处理同样是刷新实际尺寸属性;而当 EnableActualSizeBinding 变为 False 时,去掉 SizeChanged 事件的监听;

这样的结果就是,当 EnableActualSizeBinding 变为 False 时,获取到的 ActualHeight 和 ActualWidrh 一直都是变为 False 时最后一个值,不管尺寸怎么改变都不会被更新和监听;

而通过扩展设置的绑定,和直接设置 ActualHeight 和 ActualWidth 的绑定的区别就是,直接设置的方式,对于 Width 和 Height 未指定的情况绑定无效,且不会更新,而扩展的方式可以获取初始尺寸且可以实时更新;

private static void OnEnableActualSizeBindingtPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
    var baseElement = sender as FrameworkElement;
    if (baseElement == null)
    {
        return;
    }

    if ((bool)args.NewValue)
    {
        // Size may have changed while this was disabled, so we force an updated once user enables it
        UpdateActualSizeProperties(baseElement, null);

        // Subscribe to event
        baseElement.SizeChanged += UpdateActualSizeProperties;
    }
    else
    {
        // Unsubscribe from event
        baseElement.SizeChanged -= UpdateActualSizeProperties;
    }
}

在下面的 UpdateActualSizeProperties(sender, args) 方法中,可以看到绑定目标的 ActualHeight 和 ActualWidth 在改变时,会实时赋值,这样绑定的属性就能得到实时的更新。

private static void UpdateActualSizeProperties(object sender, RoutedEventArgs routedEventArgs)
{
    var baseElement = sender as FrameworkElement;
    if (baseElement == null)
    {
        return;
    }

    // Update only if needed
    var currentHeight = GetActualHeight(baseElement);
    if (currentHeight != baseElement.ActualHeight)
    {
        SetActualHeight(baseElement, baseElement.ActualHeight);
    }

    // Update only if needed
    var currentWidth = GetActualWidth(baseElement);
    if (currentWidth != baseElement.ActualWidth)
    {
        SetActualWidth(baseElement, baseElement.ActualWidth);
    }
}

代码简单分析如上,大家在实际项目中可以对这个类进行扩展,比如把 Opacity,Color 等也作为可以实时绑定的值,实现方式和 ActualHeight ActualWidth 很类似,大家可以自行扩展,然后把扩展后的类提 PR 到 UWPCOmmunityToolkit Github 中。

调用示例

我们创建了三个 Rectangle,第一个是绑定目标,第二和第三个去绑定第一个的实际尺寸;可以看到因为第二个红色矩形使用 ActualHeight 和 ActualWidth 直接进行绑定,所以并没有绑定到正确的值;而第三个浅蓝色矩形的初始绑定值是正确的;而在第一个矩形的尺寸随着 GridSplitter 变化时,红色矩形没有任何变化,而浅蓝色矩形会跟随变化更新尺寸;这和我们预期的结果是一致的。

<StackPanel x:Name="RootGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="48">
    <Grid Height="300">
        <Grid.RowDefinitions>
            <RowDefinition MinHeight="100" MaxHeight="300" />
            <RowDefinition Height="11" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="100" MaxWidth="800" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Rectangle Grid.Column="0" Grid.Row="0" extensions:FrameworkElementExtensions.EnableActualSizeBinding="True"
        Fill="Blue" Stroke="Gray" x:Name="TargetObject" StrokeThickness="1"/>

        <!--Column Grid Splitter-->
        <controls:GridSplitter Width="11" Background="Gray" GripperCursor="Default" HorizontalAlignment="Left" Grid.Column="1"
                            ResizeDirection="Auto" ResizeBehavior="BasedOnAlignment" CursorBehavior="ChangeOnGripperHover" GripperForeground="White"/>

        <!--Row Grid Splitter-->
        <controls:GridSplitter Grid.Row="1" Background="Gray" Height="11" HorizontalAlignment="Stretch">
            <controls:GridSplitter.Element>
                <Grid>
                    <TextBlock HorizontalAlignment="Center" IsHitTestVisible="False" VerticalAlignment="Center" Text=""
                            Foreground="White" FontFamily="Segoe MDL2 Assets"/>
                </Grid>
            </controls:GridSplitter.Element>
        </controls:GridSplitter>
    </Grid>

    <Rectangle Margin="12,12" HorizontalAlignment="Left"
    Height="{Binding ElementName=TargetObject, Path=ActualHeight}"
    Width="{Binding ElementName=TargetObject, Path=ActualWidth}"
    Fill="Red" Stroke="Gray" StrokeThickness="1"/>

    <Rectangle Margin="12,12" HorizontalAlignment="Left"
    Height="{Binding ElementName=TargetObject, Path=(extensions:FrameworkElementExtensions.ActualHeight)}"
    Width="{Binding ElementName=TargetObject, Path=(extensions:FrameworkElementExtensions.ActualWidth)}"
    Fill="LightBlue" Stroke="Gray" StrokeThickness="1"/>
</StackPanel>

总结

到这里我们就把 UWP Community Toolkit Extensions 中的 FrameworkElement Extensions 的源代码实现过程和简单的调用示例讲解完成了,希望能对大家更好的理解和使用这个扩展有所帮助。欢迎大家多多交流,谢谢!

最后,再跟大家安利一下 UWPCommunityToolkit 的官方微博:https://weibo.com/u/6506046490大家可以通过微博关注最新动态。

衷心感谢 UWPCommunityToolkit 的作者们杰出的工作,Thank you so much, UWPCommunityToolkit authors!!!

Extensions in UWP Community Toolkit - FrameworkElement Extensions的更多相关文章

  1. Extensions in UWP Community Toolkit - Visual Extensions

    概述 UWP Community Toolkit Extensions 中有一个为可视元素提供的扩展 - VisualExtensions,本篇我们结合代码详细讲解 VisualExtensions ...

  2. Extensions in UWP Community Toolkit - Overview

    概述 UWP Community Toolkit  中有一个 Extensions 的集合,它们可以帮助开发者实现很多基础功能,省去自己造轮子的过程,本篇我们先来看一下 Extensions 的功能都 ...

  3. Extensions in UWP Community Toolkit - Mouse Cursor

    概述 UWP Community Toolkit Extensions 中有一个为 Mouse 提供的扩展 - Mouse Cursor Extensions,本篇我们结合代码详细讲解 Mouse C ...

  4. Extensions in UWP Community Toolkit - SurfaceDialTextbox

    概述 UWP Community Toolkit Extensions 中有一个为TextBox 提供的 SurfaceDial 扩展 - SurfaceDialTextbox,本篇我们结合代码详细讲 ...

  5. Extensions in UWP Community Toolkit - ViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 View 提供的扩展 - View Extensions,本篇我们结合代码详细讲解 View Extensions  ...

  6. Extensions in UWP Community Toolkit - WebViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 WebView 提供的扩展 - WebViewExtensions,本篇我们结合代码详细讲解 WebView Ext ...

  7. Extensions in UWP Community Toolkit - ListViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 ListView 提供的扩展 - ListViewExtensions,本篇我们结合代码详细讲解 ListView  ...

  8. New UWP Community Toolkit

    概述 UWP Community Toolkit 是一个 UWP App 自定义控件.应用服务和帮助方法的集合,能够很大程度的简化和指引开发者的开发工作,相信广大 UWPer 并不陌生. 下面是截取自 ...

  9. Animations in UWP Community Toolkit - Overview

    概述 UWP Community Toolkit  中有一个 Animations 的集合,它们可以帮助开发者实现很多的动画,本篇我们先来看一下 Animations 的功能都有哪些,再后面会针对每一 ...

随机推荐

  1. scala开发环境安装

    安装JDK    java 运行环境 ,这里不详说了,熟悉java的朋友应该都会,我们主要关注下Scala的安装. 安装scala    1.下载scala    http://yunpan.cn/c ...

  2. EF ( Entity Framework) 操作ArcCataLog 生成的(Sql Server)空间数据库

    因为项目需求,现在需要利用EF 操作由Arccatalog生成的sql server空间数据库..在此之前,一直没有接触过空间数据库,在操作空间数据库时 绕了许多弯... 因此写一篇随笔做一个总结. ...

  3. 使用Angular CLI进行Build (构建) 和 Serve

    第一篇文章是: "使用angular cli生成angular5项目" : http://www.cnblogs.com/cgzl/p/8594571.html 第二篇文章是: & ...

  4. PPT分享 | 怎么在区块链上保护隐私?

    艾伯特AI人工智能(公众号:aibbtcom)按: (编者按:在12月3日的亚太区以太坊社区培训和交流Meetup深圳站上,Vitalik作了<怎么在区块链上保护隐私>的演讲,谈到了区块链 ...

  5. 萌新关于C#委托一点见解

    开博第一写C#委托(一个简单的委托) 1.关于委托,一直是学习c#的萌新们的噩梦,小生也是.最近在学委托感觉瞬间被虐成狗,但作为C#中极为重要的一个内容,学好了将会及大地减少我们的代码量,而且这也是够 ...

  6. C语言第一次博客作业

    一,PTA实验作业 题目1.温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代 ...

  7. 笔记:Spring Cloud Eureka 服务发现与消费

    服务发现与消费,其服务发现的任务是由Eureka的客户端完成,而服务的消费任务由Ribbon.JerseyClient等完成,Ribbon是一个基于HTTP和TCP的客户端负载均衡器:使用Jersey ...

  8. 吐槽net下没有靠谱的FastDFS的sdk之使用thrift实现JAVA和C#互通

    事情是这样的,在一个新项目中引入了fastdfs,用这玩意做一些小数据的存储还是很方便的,然后在nuget上就找一个对接FastDFS的sdk,如下图: 一眼就看到了这个top1的sdk,应该会比较靠 ...

  9. Java注解学习笔记

    我们平常写Java代码,对其中的注解并不是很陌生,比如说写继承关系的时候经常用到@Override来修饰方法.但是@Override是用来做什么的,为什么写继承方法的时候要加上它,不加行不行.如果对J ...

  10. 详细分析du和df的统计结果为什么不一样

    今天有个人问我du和df的统计结果为什么会不同.给他解析了一番,后来想想还是写篇文章从原理上来分析分析. 我们常常使用du和df来获取目录或文件系统已占用空间的情况.但它们的统计结果是不一致的,大多数 ...