/// <inheritdoc />
 protected override void InitializeFolderNodeLabels(FolderNodeState state, IFoldingView foldingView, INode viewNode, INode masterNode)
 {
     state.ClearLabels();
     if (CopyLabels)
     {
         var labels = masterNode.Labels;
         if (labels.Count > 0)
         {
             for (var i = 0; i < labels.Count; i++)
             {
                 var label = labels[i];
                 // If the node is a choreographyNode, just copy all Labels
                 if (masterNode.Style is ChoreographyNodeStyle)
                 {
                     state.AddLabel(label.Text, label.LayoutParameter, label.Style, label.PreferredSize, label.Tag);
                 }
                 else
                 {
                     // if subProcessNode, create new Layout & Style
                     var labelStyle = CreateLabelStyle(foldingView, null, label);
                     var labelModel = new InteriorStretchLabelModel {
                         Insets = new InsetsD(3, 3, 3, 3)
                     };
                     var labelLayoutParameter = labelModel.CreateParameter(InteriorStretchLabelModel.Position.Center);
                     state.AddLabel(label.Text, labelLayoutParameter ?? label.LayoutParameter, labelStyle ?? label.Style, label.PreferredSize, label.Tag);
                 }
             }
         }
     }
 }
示例#2
0
        protected virtual VisualToggleButton CreateButton(IRenderContext context, INode item, Visual collapsedVisual, Visual expandedVisual)
        {
            var button = new VisualToggleButton {
                CommandParameter = item, Command = GraphCommands.ToggleExpansionState, CheckedVisual = collapsedVisual, UncheckedVisual = expandedVisual, Background = iconBrush
            };

            bool expanded = true;
            var  canvas   = context != null ? context.CanvasControl : null;

            if (canvas != null)
            {
                button.CommandTarget = canvas;

                IGraph graph = canvas.Lookup(typeof(IGraph)) as IGraph;
                if (graph != null)
                {
                    IFoldingView foldingView = graph.Lookup <IFoldingView>();
                    if (foldingView != null && foldingView.Graph.Contains(item))
                    {
                        expanded = foldingView.IsExpanded(item);
                    }
                }
            }
            else
            {
                button.Content = "+";
            }

            button.IsChecked = !expanded;
            return(button);
        }
        /// <inheritdoc />
        protected override void InitializeFolderNodePorts(FolderNodeState state, IFoldingView foldingView, INode viewNode, INode masterNode)
        {
            foreach (var port in viewNode.Ports)
            {
                var masterPort = foldingView.GetMasterItem(port);
                var newStyle   = CreatePortStyle(foldingView, port, masterPort);
                var portState  = state.GetFoldingPortState(masterPort);
                if (newStyle != null)
                {
                    portState.Style = newStyle;
                }
                var newLocationParameter = CreatePortLocationParameter(foldingView, port, masterPort);
                if (newLocationParameter != null)
                {
                    portState.LocationParameter = newLocationParameter;
                }

                if (masterPort.Labels.Count > 0)
                {
                    for (var i = 0; i < masterPort.Labels.Count; i++)
                    {
                        var label                = masterPort.Labels[i];
                        var labelStyle           = CreateLabelStyle(foldingView, null, label);
                        var labelLayoutParameter = CreateLabelLayoutParameter(foldingView, null, label);

                        portState.AddLabel(label.Text, labelLayoutParameter ?? label.LayoutParameter, labelStyle ?? label.Style, label.PreferredSize, label.Tag);
                    }
                }
            }
        }
        /// <summary>
        /// Helper method for the <see cref="ShowContentsCommand"/> binding.
        /// </summary>
        private void OnCanShowContentsExecuted(object sender, CanExecuteRoutedEventArgs e)
        {
            if (graphControl == null)
            {
                e.Handled = false;
                return;
            }
            // see if we can execute the command...
            IFoldingView graph = graphControl.Graph.Lookup <IFoldingView>();

            if (graph != null)
            {
                INode node = FindNode(graph, e.Parameter);
                if (node != null)
                {
                    // yes, we found a node - notify the binding.
                    e.CanExecute = true;
                    e.Handled    = true;
                }
            }
            else
            {
                e.Handled = false;
            }
        }
        /// <summary>
        /// Helper method that identifies the node to show the contents of
        /// if <see cref="ShowContentsCommand"/> is executed.
        /// </summary>
        /// <remarks>
        /// This method will use the parameter as the return value or the currently selected node
        /// if it's a group node.
        /// </remarks>
        private INode FindNode(IFoldingView foldingView, object parameter)
        {
            INode node = parameter as INode;

            if (node != null && foldingView.Graph.Contains(node) && !foldingView.Manager.MasterGraph.IsGroupNode(foldingView.GetMasterItem(node)))
            {
                node = null;
            }
            if (node == null)
            {
                IEnumerator <INode> selectedNodes = graphControl.Selection.SelectedNodes.GetEnumerator();
                while (selectedNodes.MoveNext())
                {
                    node = selectedNodes.Current;
                    if (foldingView.Graph.Contains(node) && foldingView.Manager.MasterGraph.IsGroupNode(foldingView.GetMasterItem(node)))
                    {
                        break;
                    }
                    else
                    {
                        node = null;
                    }
                }
            }
            return(node);
        }
        /// <summary>
        /// Creates a new instance and installs it on the given <see cref="GraphControl"/>.
        /// </summary>
        /// <param name="graphControl">The control to install the z-order support on.</param>
        public ZOrderSupport(GraphControl graphControl)
        {
            GraphControl = graphControl;
            // make this ZOrderSupport available via lookup of the view graph and master graph
            AddZOrderSupportLookup(graphControl.Graph, this);
            FoldingView           = graphControl.Graph.GetFoldingView();
            MasterGraph           = FoldingView.Manager.MasterGraph;
            MasterGroupingSupport = MasterGraph.GetGroupingSupport();
            AddZOrderSupportLookup(MasterGraph, this);

            // use this ZOrderSupport as node comparer for the visualization
            graphControl.GraphModelManager = new ZOrderGraphModelManager(graphControl, this);
            // keep labels at their owners for this demo
            graphControl.GraphModelManager.LabelLayerPolicy = LabelLayerPolicy.AtOwner;

            // set a custom GraphMLIOHandler that supports writing and parsing node z-orders to/from GraphML
            graphControl.GraphMLIOHandler = new ZOrderGraphMLIOHandler();

            // use a custom edit mode to keep z-order consistent during grouping/folding/reparenting gestures
            graphControl.InputMode = new ZOrderGraphEditorInputMode(this);
            graphControl.Graph.GetDecorator().NodeDecorator.PositionHandlerDecorator.SetFactory(node => new ZOrderNodePositionHandler(node));

            // use a custom clipboard that transfers the relative z-order of copied/cut nodes
            graphControl.Clipboard = new ZOrderGraphClipboard(this);

            // listen for new nodes to assign an initial z-order
            MasterGraph.NodeCreated += OnNodeCreated;
            AddZOrderForNewNodes     = true;
        }
        /// <summary>
        /// Helper method for the <see cref="ShowContentsCommand"/> binding.
        /// </summary>
        private void OnShowContentsExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (graphControl == null)
            {
                e.Handled = false;
                return;
            }
            // get the IFoldingView instance
            IFoldingView graph = graphControl.Graph.Lookup <IFoldingView>();

            if (graph != null)
            {
                // find the node to show the contents for
                INode node = FindNode(graph, e.Parameter);
                // if we found one
                if (node != null)
                {
                    // show it
                    ShowContents(graph.GetMasterItem(node));
                    e.Handled = true;
                }
            }
            else
            {
                e.Handled = false;
            }
        }
        public override void UpdateFolderNodeState(FolderNodeState state, IFoldingView foldingView, INode viewNode, INode masterNode)
        {
            SynchronizeLabels(state, foldingView, viewNode, masterNode);

            // Copys the changed master Style to the state
            state.Style = masterNode.Style;
        }
        /// <summary>
        /// Helper method that creates a window that displays an alternative view of the
        /// MasterGraph using a separate FoldingManager and therefor a separate set of
        /// dummy items.
        /// </summary>
        /// <remarks>
        /// This allows for using different visualizations of the folding edges and collapsed group nodes.
        /// </remarks>
        /// <param name="foldingEdgeConverter">The edge converter to use</param>
        private void ShowAdditionalManager(IFoldingEdgeConverter foldingEdgeConverter)
        {
            // create the GraphControl
            GraphControl graphControl = new GraphControl();

            // create a new manager for the same master graph.
            FoldingManager manager = new FoldingManager(foldingManager.MasterGraph);

            // assign the provided converter
            manager.FoldingEdgeConverter = foldingEdgeConverter;

            // create a view
            IFoldingView foldingView = manager.CreateFoldingView();

            // make the view disappear once it becomes invalid
            foldingView.AutoSwitchToAncestor = false;
            // set the graph
            graphControl.Graph = foldingView.Graph;
            // and edit mode
            graphControl.InputMode = CreateEditorMode();
            // share the clipboard with the rest of the windows
            graphControl.Clipboard = this.graphControl.Clipboard;

            // create the form
            Form form = new Form();

            graphControl.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;

            form.Size             = new Size(300, 300);
            graphControl.Location = new Point(0, 0);
            graphControl.Size     = form.Size;
            form.Text             = "Separate FoldingManager using " + foldingEdgeConverter;
            form.SuspendLayout();
            form.Controls.Add(graphControl);
            form.ResumeLayout();
            form.Visible = true;
            form.Owner   = this;

            // fit the bounds
            graphControl.FitGraphBounds();

            // setup delegate to dispose the window once the view becomes invalid
            foldingView.PropertyChanged += delegate(object _sender, PropertyChangedEventArgs _e) {
                if (_e.PropertyName == "Invalid" && foldingView.Invalid)
                {
                    manager.Dispose();
                    form.Close();
                    form.Dispose();
                }
            };
        }
        /// <summary>
        /// Change the default style for group nodes.
        /// </summary>
        /// <remarks>We use <see cref="CollapsibleNodeStyleDecorator"/> to wrap the
        /// <see cref="PanelNodeStyle"/> from the last demo, since we want to have nice
        /// +/- buttons for collapse/expand. Note that if you haven't defined
        /// a custom group node style, you don't have to do anything at all, since
        /// <see cref="FoldingManager"/> already
        /// provides such a decorated group node style by default.</remarks>
        private void WrapGroupNodeStyles()
        {
            IFoldingView foldingView = graphControl.Graph.GetFoldingView();

            if (foldingView != null)
            {
                //PanelNodeStyle is a nice style especially suited for group nodes
                PanelNodeStyle style = new PanelNodeStyle {
                    Color = Colors.LightBlue
                };

                //Wrap the style with CollapsibleNodeStyleDecorator
                foldingView.Graph.GroupNodeDefaults.Style = new CollapsibleNodeStyleDecorator(style);
            }
        }
        /// <summary>
        /// Helper method that creates a window that displays an alternative view of the
        /// MasterGraph using a separate FoldingManager and therefore a separate set of
        /// dummy items.
        /// </summary>
        /// <remarks>
        /// This allows for using different visualizations of the folding edges and collapsed group nodes.
        /// </remarks>
        /// <param name="foldingEdgeConverter">The edge converter to use</param>
        private void ShowAdditionalManager(IFoldingEdgeConverter foldingEdgeConverter)
        {
            // create the window
            Window window = new Window();

            window.Title = "Separate FoldingManager using " + foldingEdgeConverter;

            // create the GraphControl
            GraphControl graphControl = new GraphControl();

            // create a new manager for the same master graph.
            FoldingManager manager = new FoldingManager(foldingManager.MasterGraph);

            // assign the provided converter
            manager.FoldingEdgeConverter = foldingEdgeConverter;

            // create a view
            IFoldingView foldingView = manager.CreateFoldingView();

            // make the view disappear once it becomes invalid
            foldingView.AutoSwitchToAncestor = false;
            // set the graph
            graphControl.Graph = foldingView.Graph;
            // and edit mode
            graphControl.InputMode = CreateEditorMode();
            // share the clipboard with the rest of the windows
            graphControl.Clipboard = this.graphControl.Clipboard;

            // show the window
            window.Content = graphControl;
            window.Width   = window.Height = 300;
            window.Owner   = this;
            window.Show();

            // fit the bounds
            graphControl.FitGraphBounds();

            // setup delegate to dispose the window once the view becomes invalid
            foldingView.PropertyChanged += delegate(object _sender, PropertyChangedEventArgs _e) {
                if (_e.PropertyName == "Invalid" && foldingView.Invalid)
                {
                    manager.Dispose();
                    window.Close();
                }
            };
        }
        private void ShowContents(INode localRoot)
        {
            GraphControl groupContentsGraphControl = new GraphControl();

            // now obtain a view for the given node from the manager
            IFoldingView foldingView = foldingManager.CreateFoldingView(localRoot);

            // instead of switching to the ancestor if the localRoot is removed from the graph,
            // we want to dispose the window, instead.
            foldingView.AutoSwitchToAncestor = false;

            // assign the graph and input mode
            groupContentsGraphControl.Graph     = foldingView.Graph;
            groupContentsGraphControl.InputMode = CreateEditorMode();
            // share the clipboard so that we can cut and copy between the windows
            groupContentsGraphControl.Clipboard = this.graphControl.Clipboard;

            groupContentsGraphControl.SmoothingMode = this.graphControl.SmoothingMode;

            // Create the form
            Form form = new Form();

            form.Load += delegate {
                groupContentsGraphControl.FitGraphBounds();
            };
            // show the master graph
            groupContentsGraphControl.Dock = DockStyle.Fill;
            form.ClientSize = new Size(300, 300);
            form.Text       = "Contents of " + localRoot;
            form.SuspendLayout();
            form.Controls.Add(groupContentsGraphControl);
            form.ResumeLayout();
            form.Owner   = this;
            form.Visible = true;

            // setup delegate to dispose the window once the view becomes invalid
            foldingView.PropertyChanged += delegate(object _sender, PropertyChangedEventArgs _e) {
                if (_e.PropertyName == "Invalid" && foldingView.Invalid)
                {
                    foldingView.Dispose();
                    form.Close();
                    form.Dispose();
                }
            };
        }
示例#13
0
        private bool IsExpanded(IRenderContext context, INode node)
        {
            CanvasControl canvas = context != null ? context.CanvasControl : null;

            if (canvas != null)
            {
                IGraph graph = canvas.Lookup(typeof(IGraph)) as IGraph;
                if (graph != null)
                {
                    IFoldingView foldedGraph = graph.Lookup <IFoldingView>();
                    if (foldedGraph != null && foldedGraph.Graph.Contains(node))
                    {
                        return(foldedGraph.IsExpanded(node));
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// Initializes the graph instance setting default styles
        /// and creating a small sample graph.
        /// </summary>
        protected virtual void InitializeGraph()
        {
            // Create the folding manager
            foldingManager = new FoldingManager();

            // initialize it with some default for this demo.
            InitializeFoldingManager();

            // initialize the master graph
            foldingManager.MasterGraph.GroupNodeDefaults.Style =
                new CollapsibleNodeStyleDecorator(new PanelNodeStyle {
                Color = Colors.LightSkyBlue
            });
            foldingManager.MasterGraph.NodeDefaults.Style = new BevelNodeStyle {
                Color = Colors.Black
            };

            // enable undoability on the master graph
            foldingManager.MasterGraph.SetUndoEngineEnabled(true);

            // create a managed view
            IFoldingView view = foldingManager.CreateFoldingView();

            view.EnqueueNavigationalUndoUnits = true;

            // and display it
            graphControl.Graph = view.Graph;

            IGraph graph = foldingManager.MasterGraph;

            // try loading the initial sample graph
            try {
                string s = Environment.CurrentDirectory;
                graphControl.ImportFromGraphML(new FileInfo(s + "\\sample.graphml"));
            } catch (IOException) {
                // create initial sample data in our model
                CreateInitialModelGraph(graph);
            }
        }
示例#15
0
        public override IVisual CreateVisual(IRenderContext context)
        {
            collapsedIcon.SetBounds(new RectD(Bounds.GetTopLeft(), Bounds.GetSize()));
            expandedIcon.SetBounds(new RectD(Bounds.GetTopLeft(), Bounds.GetSize()));
            bool expanded = true;

            CanvasControl canvas = context != null ? context.CanvasControl : null;

            if (canvas != null)
            {
                IGraph graph = canvas.Lookup(typeof(IGraph)) as IGraph;
                if (graph != null)
                {
                    IFoldingView foldedGraph = graph.Lookup <IFoldingView>();
                    if (foldedGraph != null && foldedGraph.Graph.Contains(node))
                    {
                        expanded = foldedGraph.IsExpanded(node);
                    }
                }
            }
            return(expanded ? expandedIcon.CreateVisual(context) : collapsedIcon.CreateVisual(context));
        }
        private void ShowContents(INode localRoot)
        {
            Window window = new Window();

            window.Title = "Contents of " + localRoot;
            // we create a new control
            GraphControl groupContentsGraphControl = new GraphControl();

            // now obtain a view for the given node from the manager
            IFoldingView foldingView = foldingManager.CreateFoldingView(localRoot);

            // instead of switching to the ancestor if the localRoot is removed from the graph,
            // we want to dispose the window, instead.
            foldingView.AutoSwitchToAncestor = false;

            // assign the graph and input mode
            groupContentsGraphControl.Graph     = foldingView.Graph;
            groupContentsGraphControl.InputMode = CreateEditorMode();
            // share the clipboard so that we can cut and copy between the windows
            groupContentsGraphControl.Clipboard = this.graphControl.Clipboard;

            // show the window
            window.Content = groupContentsGraphControl;
            window.Width   = window.Height = 300;
            window.Owner   = this;
            window.Show();

            // and fit the bounds
            window.Dispatcher.BeginInvoke(new Action(() => groupContentsGraphControl.FitGraphBounds()));

            // register a delegate that will dispose the window when the view gets invalid
            foldingView.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) {
                if (e.PropertyName == "Invalid" && foldingView.Invalid)
                {
                    window.Close();
                }
            };
        }
示例#17
0
        internal static TierType GetTierType(INode node, IFoldingView foldingView, IGraph graph)
        {
            if (graph.IsGroupNode(node)
                // node is an expanded group node
                || foldingView.IsInFoldingState(node))
            {
                string labelText = (node.Labels.Count > 0)
          ? node.Labels[0].Text
          : "";
                switch (labelText)
                {
                case "left":
                    return(TierType.LeftTreeGroupNode);

                case "right":
                    return(TierType.RightTreeGroupNode);

                default:
                    return(TierType.CommonNode);
                }
            }
            return(TierType.CommonNode);
        }
示例#18
0
        /// <summary>
        /// Initializes the graph instance, setting default styles
        /// and creating a small sample graph.
        /// </summary>
        protected virtual void InitializeGraph()
        {
            // create the manager for the folding operations
            FoldingManager foldingManager = new FoldingManager();

            // create a view
            foldingView = foldingManager.CreateFoldingView();

            // and set it to the GraphControl
            graphControl.Graph = foldingView.Graph;

            // decorate the behavior of nodes
            NodeDecorator nodeDecorator = graphControl.Graph.GetDecorator().NodeDecorator;

            // adjust the insets so that labels are considered
            nodeDecorator.InsetsProviderDecorator.SetImplementationWrapper(
                delegate(INode node, INodeInsetsProvider insetsProvider) {
                if (insetsProvider != null)
                {
                    InsetsD insets = insetsProvider.GetInsets(node);
                    return(new LabelInsetsProvider(insets));
                }
                else
                {
                    return(new LabelInsetsProvider());
                }
            });

            //Constrain group nodes to at least the size of their labels
            nodeDecorator.SizeConstraintProviderDecorator.SetImplementationWrapper(
                (node, oldImpl) => new LabelSizeConstraintProvider(oldImpl));

            fixedGroupNodeLayout = graphControl.Graph.MapperRegistry.CreateMapper <INode, RectD?>("NodeLayouts");
            ReadSampleGraph();
            incrementalNodes.UnionWith(graphControl.Graph.Nodes);
        }
        /// <summary>
        /// Called by <see cref="UpdateFolderNodeState" /> to synchronize all labels, if <see cref="CopyLabels" />
        /// is enabled. Also synchronizes all port labels of ports connected to the node.
        /// </summary>
        /// <remarks>This will adjust the label text property.</remarks>
        /// <param name="state">The node view state whose labels should be synchronized.</param>
        /// <param name="foldingView">The folding view.</param>
        /// <param name="viewNode">The local node instance.</param>
        /// <param name="masterNode">The master node.</param>
        protected override void SynchronizeLabels(FolderNodeState state, IFoldingView foldingView, INode viewNode, INode masterNode)
        {
            if (CopyLabels)
            {
                if (masterNode.Labels.Count > 0 && state.Labels.Count > 0)
                {
                    for (var i = 0; i < masterNode.Labels.Count; i++)
                    {
                        var masterLabel    = masterNode.Labels[i];
                        var labelViewState = state.Labels[i];
                        labelViewState.Text          = masterLabel.Text;
                        labelViewState.PreferredSize = masterLabel.PreferredSize;
                        labelViewState.Tag           = masterLabel.Tag;
                    }
                }

                if (masterNode.Ports.Count > 0)
                {
                    for (var j = 0; j < masterNode.Ports.Count; j++)
                    {
                        var port = masterNode.Ports[j];
                        if (port.Labels.Count > 0)
                        {
                            for (var i = 0; i < port.Labels.Count; i++)
                            {
                                var masterLabel    = port.Labels[i];
                                var labelViewState = state.Ports[j].Labels[i];
                                labelViewState.Text          = masterLabel.Text;
                                labelViewState.PreferredSize = masterLabel.PreferredSize;
                                labelViewState.Tag           = masterLabel.Tag;
                            }
                        }
                    }
                }
            }
        }
示例#20
0
        private void ArrangeItems(List <INode> newMasterItems, IFoldingView foldingView)
        {
            // sort new items by the relative z-order transferred in OnCopiedFromClipboard
            newMasterItems.Sort((node1, node2) => GetZOrder(node1) - GetZOrder(node2));
            var gmm = Support.GraphControl.GraphModelManager;

            // group new nodes by common parent canvas object groups of their main canvas objects
            var itemsNotInView = new List <INode>();
            var groupToItems   = new Dictionary <ICanvasObjectGroup, List <INode> >();

            foreach (var masterItem in newMasterItems)
            {
                var viewItem = foldingView != null?foldingView.GetViewItem(masterItem) : masterItem;

                if (viewItem == null)
                {
                    // new item is not in view (e.g. child of a collapsed folder node)
                    itemsNotInView.Add(masterItem);
                }
                else
                {
                    var co = gmm.GetMainCanvasObject(viewItem);
                    if (co == null)
                    {
                        itemsNotInView.Add(masterItem);
                    }
                    else
                    {
                        var          coGroup = co.Group;
                        List <INode> newNodesInGroup;
                        if (!groupToItems.TryGetValue(coGroup, out newNodesInGroup))
                        {
                            newNodesInGroup       = new List <INode>();
                            groupToItems[coGroup] = newNodesInGroup;
                        }
                        newNodesInGroup.Add(viewItem);
                    }
                }
            }
            // set z-order items not in view just in ascending order
            for (var i = 0; i < itemsNotInView.Count; i++)
            {
                Support.SetZOrder(itemsNotInView[i], i);
            }

            // for each common parent set ascending z-orders for new nodes
            foreach (var groupItemsPair in groupToItems)
            {
                var itemsInGroup = groupItemsPair.Value;

                // find the top-most node that wasn't just added and lookup its z-order
                INode         topNodeNotJustAdded = null;
                ICanvasObject walker = groupItemsPair.Key.Last;
                while (walker != null)
                {
                    var node = gmm.GetModelItem(walker) as INode;
                    if (node != null && !itemsInGroup.Contains(node))
                    {
                        topNodeNotJustAdded = node;
                        break;
                    }
                    walker = walker.Previous;
                }
                var nextZOrder = topNodeNotJustAdded != null?GetZOrder(topNodeNotJustAdded) + 1 : 0;

                // set new z-orders starting from nextZOrder
                foreach (var node in itemsInGroup)
                {
                    Support.SetZOrder(node, nextZOrder++);
                }
                // update the view using the new z-orders
                foreach (var node in itemsInGroup)
                {
                    Support.Update(node);
                }
            }
        }
 public MasterViewConversionMapper(IGraph viewGraph)
 {
     this.viewGraph = viewGraph;
     foldingView    = viewGraph.GetFoldingView();
     masterGraph    = foldingView.Manager.MasterGraph;
 }
示例#22
0
 public static T GetMaster <T>(this IFoldingView fv, T item) where T : class, IModelItem
 {
     return(fv.GetMasterItem(item));
 }