设为首页 加入收藏

TOP

【UWP】实现 FindAncestor 绑定(一)
2019-09-17 17:25:00 】 浏览:36
Tags:UWP 实现 FindAncestor 绑定

在 WPF 里,我们是可以在 RelativeSource 上面实现的,举个例子:

<Grid Tag="2">
    <Button>
        <Grid Tag="1">
            <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid, AncestorLevel=2}, Path=Tag, Mode=OneWay}" />
        </Grid>
    </Button>
</Grid>

将 RelativeSource 的 Mode 设置为 FindAncestor 就可以了。AncestorType 代表绑定的类型,AncestorLevel 代表查询第几个,默认是 1。所以在上面的例子里,由于 AncestorLevel 是 2,所以查询出来的是 Tag 等于 2 的那个 Grid。假如设置成 3,那就查询不到了。

 

但是,在 UWP 里,微软出于性能考虑,把 FindAncestor 给去掉了,RelativeSource 的 Mode 只剩下了 Self 和 TemplateParent。但是需求永远是存在的,那么总得有个解决方案吧,假如你搜索过 Google 或者 StackOverflow,无一不例外就是改成通过 ElementName 来绑定,也就是上面的例子会变成如下这样:

<Grid x:Name="TargetGrid"
      Tag="2">
    <Button>
        <Grid Tag="1">
            <TextBlock Text="{Binding ElementName=TargetGrid, Path=Tag, Mode=OneWay}" />
        </Grid>
    </Button>
</Grid>

说实话这样也能用,而且性能更好了,一直以来,我自己的 UWP 项目也是通过这种方式来解决。

 

但是,在前段时间我开发我自己的图片缓存控件(https://github.com/h82258652/HN.Controls.ImageEx)时,就发现了一个无法解决的问题。图片控件 ImageEx 提供了一个 DownloadProgress 的属性可以获取当前图片的下载进度。另外该控件还有一个 LoadingTemplate 的属性,可以设置一个模板,在图片加载的过程显示。现在我想在加载的时候显示一个进度条,于是乎就有了以下代码:

<controls:ImageEx x:Name="TargetImage">
    <controls:ImageEx.LoadingTemplate>
        <DataTemplate>
            <ProgressBar Maximum="1"
                         Value="{Binding ElementName=TargetImage, Path=DownloadProgress.Percentage, Mode=OneWay}" />
        </DataTemplate>
    </controls:ImageEx.LoadingTemplate>
</controls:ImageEx>

这样单个 ImageEx 就没问题了,但是需求再进一步,我需要所有的 ImageEx 都是这样,LoadingTemplate 是一致的。在此刻,我们已经没办法通过绑定 ElementName 的方式来解决问题了。

 

俗话说,不行就包一层。XAML 里包一层的话,那就是 ContentControl 了,这里我们创建一个叫 AncestorBindingAssist 的模板控件,继承自 ContentControl。

cs 代码如下:

public class AncestorBindingAssist : ContentControl
    {
        public static readonly DependencyProperty AncestorLevelProperty = DependencyProperty.Register(nameof(AncestorLevel), typeof(int), typeof(AncestorBindingAssist), new PropertyMetadata(1, OnAncestorLevelChanged));
        public static readonly DependencyProperty AncestorTypeProperty = DependencyProperty.Register(nameof(AncestorType), typeof(Type), typeof(AncestorBindingAssist), new PropertyMetadata(default(Type), OnAncestorTypeChanged));
        public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(nameof(Source), typeof(DependencyObject), typeof(AncestorBindingAssist), new PropertyMetadata(default(DependencyObject)));

        public AncestorBindingAssist()
        {
            DefaultStyleKey = typeof(AncestorBindingAssist);
        }

        public int AncestorLevel
        {
            get => (int)GetValue(AncestorLevelProperty);
            set => SetValue(AncestorLevelProperty, value);
        }

        public Type AncestorType
        {
            get => (Type)GetValue(AncestorTypeProperty);
            set => SetValue(AncestorTypeProperty, value);
        }

        public DependencyObject Source
        {
            get => (DependencyObject)GetValue(SourceProperty);
            private set => SetValue(SourceProperty, value);
        }

        protected override void OnApplyTemplate()
        {
            UpdateSource();
        }

        private static void OnAncestorLevelChanged(DependencyObject d, Depende
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇IdentityServer4笔记整理(更新中) 下一篇TreeViewItem节点添加图标后再加h..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目