检查指定的元素是否已经是另一个元素的逻辑子元素

时间:2016-01-31 09:57:04

标签: c# wpf visual-tree visualtreehelper logical-tree

我是C#和WPF的初学者。我是一个名为vvvv的基于节点的软件的编程插件。我已经实现了滑块,按钮和其他简单的UI元素。以下代码显示了滑块节点在c#中的外观:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xml;
using VVVV.PluginInterfaces.V2;

namespace VVVV.Packs.UI.Nodes.WPF
{
    [PluginInfo(Author = "lecloneur", Category = "WPF", Help = "WPF Slider", Name = "Slider", AutoEvaluate = false)]

    public class WPFSlider : GenericNode, IPluginEvaluate
    {
        [Input("SizeX", DefaultValue = 120, Order = 9, MinValue = 0)]
        public IDiffSpread<int> SizeX;

        [Input("SizeY", DefaultValue = 120, Order = 9, MinValue = 0)]
        public IDiffSpread<int> SizeY;

        [Input("Orientation", Order = 1, DefaultEnumEntry = "Horizontal")]
        public IDiffSpread<Orientation> OrientationIn;

        [Output("Value", Order = 2)]
        public ISpread<double> ValueOut;

        int elements_count = 0;

        public void Evaluate(int SpreadMax)
        {
            UIElementOut.SliceCount = SpreadMax;
            ValueOut.SliceCount = SpreadMax;
            for (int i = 0; i < SpreadMax; i++)
            {
                if (UIElementOut == null || !(UIElementOut[0] is Slider) || elements_count < SpreadMax || OrientationIn.IsChanged || SizeX.IsChanged || SizeY.IsChanged)
                {
                    CreateElement(i);
                }
                OutputData(i);
                Transformation(i, (Slider)UIElementOut[i]);
            }
            elements_count = SpreadMax;
        }

        private void CreateElement(int i)
        {
            UIElementOut[i] = new Slider();
            var uiElement = (Slider)UIElementOut[i];
            uiElement.Minimum = 0;
            uiElement.Maximum = 1;
            uiElement.Orientation = OrientationIn[i];
            uiElement.IsMoveToPointEnabled = true;
            uiElement.Width = SizeX[i]; ;
            uiElement.Height = SizeY[i];
            uiElement.VerticalAlignment = VerticalAlignment.Center;
            uiElement.HorizontalAlignment = HorizontalAlignment.Center;

            XmlReader XmlRead = XmlReader.Create("Styles/SliderStyle.xaml");
            ResourceDictionary myResourceDictionary = (ResourceDictionary)XamlReader.Load(XmlRead);
            XmlRead.Close();
            Style uiElementStyle = myResourceDictionary["SliderStyle"] as Style;
            uiElement.Style = uiElementStyle;
        }

        private void OutputData(int i)
        {
            var uiElement = (Slider)UIElementOut[i];
            ValueOut[i] = uiElement.Value;
        }
    } 
}

现在我试图实现一个tabcontrol,我可以在其中动态创建tabitem并输入UIElement。据我所知,我只能在一个tabitem中添加一个东西。所以我在考虑每次需要时创建一个网格,并用所有传入的UIElement填充它。

    public void Evaluate(int SpreadMax)
    {
        SpreadMax = 1;

        UIElementOut.SliceCount = 1;

        for (var i = 0; i < SpreadMax; i++)
        {
            if (UIElementOut == null || !(UIElementOut[i] is TabControl))
                UIElementOut[i] = new TabControl();
                var uiElement = (TabControl)UIElementOut[i];
                uiElement.Height = 200;
                uiElement.Width = 500;
        }



        Grid grid;

        int[] _elementCounts = new int[_elementInputs.SliceCount];

        for (var i = 0; i < _elementInputs.SliceCount; i++)
        {
            if (_elementInputs[i] == null || !(_elementInputs[i] is UIElement))
            {
                grid = new Grid();

                for (var j = 0; j < _elementInputs[i].IOObject.SliceCount; j++)
                {
                    if (_elementInputs[i].IOObject[j] != null)
                    {
                        UIElement test = new UIElement();
                        test = _elementInputs[i].IOObject[j];
                        grid.Children.Add(test);
                    }
                }
                _elementCounts[i] = _elementInputs[i].IOObject.SliceCount;
                ValueOut[i] = _elementCounts[i];


                if (((TabControl)UIElementOut[0]).Items.Count <= i)
                {
                    ((TabControl)UIElementOut[0]).Items.Add(new TabItem { Header = _nameInputs[i].IOObject[0], Content = grid });
                }

                if (_nameInputs[i].IOObject.IsChanged)
                {
                    ((TabItem)((TabControl)UIElementOut[0]).Items[i]).Header = _nameInputs[i].IOObject[0];
                }

                if (_elementInputs[i].IOObject.IsChanged)
                {
                    ((TabItem)((TabControl)UIElementOut[0]).Items[i]).Content = grid;
                }
            }
        }

        for (var i = ((TabControl)UIElementOut[0]).Items.Count - 1; ((TabControl)UIElementOut[0]).Items.Count > _elementInputs.SliceCount; i--)
        {
            ((TabControl)UIElementOut[0]).Items.RemoveAt(i);
        }
    }

我搜索了很多,但无法找到解决错误的方法。显然在网格中添加元素&#34;指定的元素已经是另一个元素的逻辑子元素了#34 ;;

1 个答案:

答案 0 :(得分:1)

您好请在几个可视对象(子)上尝试下一个方法,并检查结果对象是否是相同的引用。 Here is a usefull link with explanations and more...

扩展类代码:

public static class VisualTreeHelperExtensions
{
    public static T FindParent<T>(this DependencyObject child) where T : DependencyObject
    {
        while (true)
        {
            //get parent item
            DependencyObject parentObject = VisualTreeHelper.GetParent(child);

            //we've reached the end of the tree
            if (parentObject == null) return null;

            //check if the parent matches the type we're looking for
            T parent = parentObject as T;
            if (parent != null)
                return parent;
            child = parentObject;
        }
    }
}

示例:

var dataGrid1 = dependencyObject1.FindParent<DataGrid>();
var dataGrid2 = dependencyObject2.FindParent<DataGrid>();
var isSameObject = dataGrid1 == dataGrid2;

<强>更新

  1. 网格可以包含大量元素,但用户只能看到唯一的元素。
  2. 错误来自你要添加的元素,elemnt属于另一个控件(另一个控件将元素作为子元素)。
  3. 找到要添加的元素的父元素,从当前父元素集合中删除元素,并将此元素添加为网格的新子元素。
  4. 尝试使用snoop来确定谁是您元素的父元素(包含在_elementInputs中)。
  5. 以下是一些有用的链接(firstsecond)。
  6. 更新2

    1. 据我所知,您的项目中有第三方基础架构,因为我无法解析_elementInputs和UIElementOut集合的类型。
    2. 由于_elementInputs是一个字段,我仍然无法理解_elementInputs来自哪里(无法在代码中看到)。
    3. 添加全新元素的代码是错误的:
    4. 正确的代码(在我看来)

                      //here is in my opinion the correct algorithm in this case
                      var elementFromInputs = _elementInputs[i] as UIElement;
                      if (elementFromInputs == null) continue;
                      //try to find parent of type Panel
                      var parentPanel = elementFromInputs.FindParent<Panel>();
                      //try to find parent of type ContentControl
                      var parentContentControl = elementFromInputs.FindParent<ContentControl>();
                      if (parentPanel == null && parentContentControl == null)
                      {
                          //add if there is no any parents
                          grid.Children.Add(elementFromInputs);
                      }
                      if (parentPanel != null)
                      {
                          //remove element from parent's collection
                          parentPanel.Children.Remove(elementFromInputs);
                      }
                      if(parentContentControl != null)
                      {
                          //reset parent content to release element
                          parentContentControl.Content = null;
                      }
                      grid.Children.Add(elementFromInputs);
      

      更新3

      您已将代码(来自正确的代码部分)粘贴到if {哪个条件为_elementInputs[i] == null || !(_elementInputs[i] is UIElement)内,这意味着将所有UIElements过滤到范围之外。由于我不熟悉vvvv概念,我不知道你在_elementInputs数组中有什么,但是如果你有UIElements,你需要通过我在if with条件{{{ 1}}。

      请在下一个说明中更新您的问题: 1. _elementInputs [i]里面有什么? 2. _elementInputs [i] .IOObject中有什么内容? 3.您想要添加到网格的UIElements是什么? 4.请运行下一个方法并将评论写在网格和TabControl控件中。

      测试代码

      _elementInputs[i] == null || !(_elementInputs[i] is UIElement)

      如果你的代码有问题,我很乐意提供帮助。 问候。