• 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

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

  • 相关阅读:
    ERP Odoo开发--Getting started with Odoo development --openerp
    5 Tips for Building a Winning DevOps Culture
    android stream media
    LDAP summary-- Python ldap
    android call and audio
    android bluetooth
    .windows安装使用这些偏底层的Python扩展太
    经典的DOS小命令 for 网络 nbtstat
    js和jquery设置disabled属性为true使按钮失效
    Several ports (8005, 8080, 8009)被占用
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1894156.html
Copyright © 2020-2023  润新知