zoukankan      html  css  js  c++  java
  • WPF的两棵树与绑定

    先建立测试基类

    public class VisualPanel : FrameworkElement
    {
        protected VisualCollection Children { get; set; }
    
        public VisualPanel()
        {
            Children = new VisualCollection(this);
        }
    
        protected override int VisualChildrenCount
        {
            get
            {
                return Children.Count;
            }
        }
    
        protected override Visual GetVisualChild(int index)
        {
            return Children[index];
        }
    
        protected override Size ArrangeOverride(Size finalSize)
        {
            if (VisualChildrenCount>0)
            {
                (Children[0] as FrameworkElement).Arrange(new Rect(0, 0, 100, 25));
            }
            return base.ArrangeOverride(finalSize);
        }
    }

    添加元素,并将加入到Window窗体中

    public class  VisualTest  : VisualPanel
    {
        public  TextBlock  textblock;
    
        private void  TestVisual()
        {
            textblock = new  TextBlock() { Text = "Hello", Background = Brushes.Red };
            this.Children.Add(textblock);
        }
    
        public  VisualTest()
        {
            TestVisual();
        }
    }

    效果

    image

    视觉树绑定测试

    //test1
    textblock.SetBinding(TextBlock.TextProperty, new Binding("Title")
    {
        RelativeSource =
            new RelativeSource() { Mode = RelativeSourceMode.FindAncestor, AncestorType = typeof(Window) }
    });
    //test2
    this.Tag = "Test";
    textblock.SetBinding(TextBlock.TextProperty, new Binding("Tag")
    {
        RelativeSource =
            new RelativeSource() { Mode = RelativeSourceMode.FindAncestor, AncestorType = typeof(VisualTest) }
    });

    测试均通过
    imageimage

    使用ElementName绑定

    //test3
    this.Name = "VisualTest";
    
    textblock.SetBinding(TextBlock.TextProperty, new Binding("Tag")
    {
        ElementName = this.Name
    });

    可以参考这里
    http://www.cnblogs.com/Clingingboy/archive/2010/11/29/1891253.html

    结果错误

    image

    设置NameScope

    this.Name = "VisualTest";
    NameScope ns = new NameScope();
    NameScope.SetNameScope(this, ns);
    this.RegisterName(this.Name, this);
    textblock.SetBinding(TextBlock.TextProperty, new Binding("Tag")
    {
        ElementName = this.Name
    });

    测试再次未通过

    将元素添加到逻辑树当中

    this.Name = "VisualTest";
    NameScope ns = new NameScope();
    NameScope.SetNameScope(this, ns);
    this.RegisterName(this.Name, this);
    AddLogicalChild(textblock);
    textblock.SetBinding(TextBlock.TextProperty, new Binding("Tag")
    {
        ElementName = this.Name
    });

    测试通过

    去除视觉树只添加逻辑树的情况

    private void TestLogic()
    {
        textblock = new TextBlock() { Text = "Hello", Background = Brushes.Red };
        this.Tag = "Test";
        this.Name = "VisualTest";
        NameScope ns = new NameScope();
        NameScope.SetNameScope(this, ns);
        this.RegisterName(this.Name, this);
        AddLogicalChild(textblock);
        textblock.SetBinding(TextBlock.TextProperty, new Binding("Tag")
        {
            ElementName = this.Name
        });
    }

    现在UI将一片空白,但绑定成功

    image

    重写ArrangeOverride方法

    protected override Size ArrangeOverride(Size finalSize)
    {
        textblock.Arrange(new Rect(0, 0, 100, 25));
        return base.ArrangeOverride(finalSize);
    }

    即使重写也无效,wpf依赖于VisualChildrenCount和GetVisualChild方法.

    总结

    绑定的ElementName依赖于NameScope和逻辑树,

    FindAncestor的查找方式则依赖于视觉树

    测试的父元素逻辑树与视觉树不一致的情况

    private void TestTwoTree()
    {
        var visual = new VisualTest(string.Empty);
        visual.Name = "InternalPanel";
        textblock = new TextBlock() { Text = "Hello", Background = Brushes.Red };
        visual.AddLogicalChild(textblock);
        this.Children.Add(textblock);
    }

    现在TextBlock有两个父元素一个是逻辑父元素InternalPanel,一个是外部的VisualTest.

    绑定逻辑父元素

    private void TestTwoTree()
    {
        var visual = new VisualTest(string.Empty);
        visual.Name = "InernalPanel";
        NameScope ns = new NameScope();
        NameScope.SetNameScope(visual, ns);
        visual.RegisterName(visual.Name, visual);
        textblock = new TextBlock() { Text = "Hello", Background = Brushes.Red };
        textblock.SetBinding(TextBlock.TextProperty, new Binding("Name")
        {
            ElementName = visual.Name
        });
        visual.AddLogicalChild(textblock);
        this.Children.Add(textblock);
    }

    测试结果

    image

    这样就实现了可以在不同父元素的绑定,通过这个例子也可以看到逻辑树与视觉树的不同之处

  • 相关阅读:
    视频智能云组网EasyNTS中sqlite和mysql数据库如何进行相互切换?
    关于github上提出EasyRTSPLive视频网关编译过程中修复README错误
    IPC拉转推流场景中如何实现视频网关EasyRTSPLive试用多通道转换?
    如何使用流媒体接入网关实现拉RTSP流转推RTMP流到流媒体服务器?
    视频流媒体平台采用Go语言编程ioutil.ReadAll的用法注意点
    视频流媒体直播平台EasyDSS运行报Only one usage错误原因排查分析
    视频流媒体播放器EasyPlayer.js截取base64编码快照显示不完整问题解决
    视频流媒体RTMP推流组件在Chorme浏览器无法播放FLV匿名直播流问题分析
    视频流媒体直播点播平台如何获取视频转码信息和进度?
    部署国标GB28181流媒体服务器EasyGBS成功后无法播放视频问题步骤排查
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1894156.html
Copyright © 2011-2022 走看看