locked
Find a Xaml element by DataContext

    Question

  • In my C++ Metro app, I want to iterate the FrameworkElement^'s of a page to find an object that has a particular DataContext.  I have no problem getting to the root panel, and inspecting it's children... I'm just hoping to forgo writing the code to run through a template'd elements control template to continue the search if possible.

    Is there either a sample somewhere of iterating the FrameworkElements on a page (even through the ControlTemplates), or better yet, that I've just missed some helper class similar to the C# VisualTreeHelper that can do this already on the C++ side of the fence.

    Oh... I really do want to search for a DataTemplate, and not for a named object. I know about FrameworkElement::FindName, and understand it's use.  Call me a rebel, but I really don't want to name the objects unless done by a designer for their own benefit.

    Thanks


    Jim Tomasko

    Tuesday, September 18, 2012 2:53 AM

Answers

  • Hi,

    I convert the traversal visual tree function to C++/CX, and hope these codes can help you.

    Windows::UI::Xaml::FrameworkElement^ FindVisualChildByName(DependencyObject^ obj, String^ name)
    {
    	FrameworkElement^ ret ;
    	int numChildren = VisualTreeHelper::GetChildrenCount(obj);
    	 for (int i = 0; i < numChildren; i++)
                {
                    auto objChild = VisualTreeHelper::GetChild(obj, i);
                    auto child = safe_cast<FrameworkElement^>(objChild);
    				if (child != nullptr && child->Name == name)
                    {
                        return child;
                    }
    
                    ret = FindVisualChildByName(objChild, name);
    				if (ret != nullptr)
                        break;
                }
                return ret;
    }
    


    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by James Tomasko Wednesday, September 19, 2012 12:49 AM
    Tuesday, September 18, 2012 6:27 AM

All replies

  • Hi,

    I convert the traversal visual tree function to C++/CX, and hope these codes can help you.

    Windows::UI::Xaml::FrameworkElement^ FindVisualChildByName(DependencyObject^ obj, String^ name)
    {
    	FrameworkElement^ ret ;
    	int numChildren = VisualTreeHelper::GetChildrenCount(obj);
    	 for (int i = 0; i < numChildren; i++)
                {
                    auto objChild = VisualTreeHelper::GetChild(obj, i);
                    auto child = safe_cast<FrameworkElement^>(objChild);
    				if (child != nullptr && child->Name == name)
                    {
                        return child;
                    }
    
                    ret = FindVisualChildByName(objChild, name);
    				if (ret != nullptr)
                        break;
                }
                return ret;
    }
    


    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by James Tomasko Wednesday, September 19, 2012 12:49 AM
    Tuesday, September 18, 2012 6:27 AM
  • "I want to iterate the FrameworkElement^'s of a page to find an object that has a particular DataContext":

    - you recurse - top down - the visual tree using VisualTreeHelper::GetChildrenCount & ::GetChild. The beauty of VisualTreeHelper is that it "doesn't care" whether tree visuals have been created thru templating or not; hence it reasons in terms of 'children' [of type DependencyObject].
    - you typically would recurse on/after the 'Loaded' event of the RootPage, since that guarantees that the visual tree beneath has been constructed [and that the DataContext is set throughout the tree]
    - to identify the DataContext for each found DependencyObject, you must first test it to be a FrameworkElement^ since 'DataContext' is a property of a FrameworkElement^ [or one of its subclasses]

    "I really do want to search for a DataTemplate":

    - the above explains the DataTemplate concept to be orthogonal to the DataContext. So, you can ignore DataTemplates to find a DataContext.
    - if you nevertheless want to access the DataTemplate of (e.g.) a ContentControl.ContentTemplate, you can do so: in the above recursion test the DependencyObject to be a ContentControl, check whether its ContentControl.ContentTemplate is set and access it as its DataTemplate. It won't give you much additional info though.

    A remark about naming:

    - if you use Names on FrameworkElements inside a DataTemplate 'referenced by' the ContentTemplate  of 2 ContentControls (e.g.), these names will be duplicated in the generated DependencyObjects of the VisualTree. In this example, you'll find the [same] Names twice in the visual tree.
    - so I agree with you: I try to avoid using Names whenever I can since fetching by name in the complete visual tree can give an ambiguous result.

    Tuesday, September 18, 2012 6:36 AM