1

I have problem with WPF - I'm quiet new in this smart technology. So the problem is:

I have a window. In this window's resources I have stored an element - eg. a Grid with unique key (assume x:Key="myGrid"). In this Grid I have a TextBox identified by a name (x:Name="myTextBox"). My Window contains only an empty Grid (named eg. winGrid). I programmatically set the myGrid as a child of the winGrid. And now, in runtime, I want to get a reference to the myTextBox object. I spent plenty of time googling, but nothing worked for me (FindName and similar methods).

Do you have please any idea, what I have to do to get the ball rolling?

Here is (pseudo)code snippet once more:

<Window x:Class="LoginForm.RidicWindow"
    ...>
<Window.Resources>
    <Grid x:Key="myGrid">
        <Border...
        <Grid...
            ...
            <TextBlock x:Name="myTextBlock" Grid.Column="0".../>
         </Grid>
    </Grid>
 </Window.Resources>
 <Grid x:Name="winGrid">
     ...
 </Grid>

And now I set the myGrid as a child of winGrid: (something like)

winGrid.Childrens.Clear();
winGrid.Childrens.Add((Grid)FindResource(myGrid));

And now I want to get a reference to myTextBlock, which is descendant of the myGrid.

I tried something like

((Grid)FindResource(myGrid)).FindByName("myTextBlock");

this, of course, doesn't work.

Hope you understand me, what I want to get. Lot of thanks!

Jan Drozen
  • 894
  • 2
  • 12
  • 28
  • This may have something to do with how wpf/xaml handles namescopes [link](http://msdn.microsoft.com/en-us/library/ms746659.aspx), it says resource dictionaries dont use them, so it may not be wiring up the names in the background when it creates your controls. I beleive the intended way of doing what you are trying to achieve would be to make a UserControl that contains your 'myGrid', and then add a new instance of that UserControl to 'winGrid'. THen you can just get a reference to the UserControl and FindName on it (e.g. `var uc = (FrameworkElement)winGrid.Children[0]; uc.FindName("...");` – a little sheep Jun 26 '12 at 23:02

3 Answers3

3

You can not do this (By the way, you can, but it's really bad, ugly and not recommended) The resources of a window to serve another purpose.

As mentioned, you must create a component (Usercontrol or other).. Although there are some other options for what you seek. You can try some of what I wrote below:


1) Creating a custom component may be a UserControl, Grid or anything else...

    <Grid x:Class="Project.MyGridControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
<!-- Content -->
    </Grid>

and

        MyGridControl control = new MyGridControl();
        winGrid.Childrens.Add(control);


2) A little more complicated:

<Grid  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <!-- Content -->
</Grid>

and

Grid myCustomGrid = XamlReader.Load(uriResource) as Grid;
winGrid.Childrens.Add(myCustomGrid);

In this option you will not have like a grid control to instantiate. (I see it often used in reports). You should create a .xaml and define it as a resource.


To find components you should look in the visual tree (as already responded)...

( How can I find WPF controls by name or type? )

Community
  • 1
  • 1
J. Lennon
  • 3,311
  • 4
  • 33
  • 64
  • Thanx! Yes, I know there are better ways to get the same (visually) solution. Now I'm doing it a little bit different. But...since I've met with this problem, I would like to have a solution for it or know, why it isn't possible. One assoc. professor says: One doesn't say "I have a problem" but "I have a challenge" :) – Jan Drozen Jun 27 '12 at 11:34
0

The comment from a little sheep provides a good start, though I'd recommend creating a UserControl, then just exposing the TextBox through a property on the control to simplify things.

However, if your design calls for you to use the approach you outline above, you will need to use the VisualTreeHelper, and specifically the GetChild() method to navigate the VisualTree to find the TextBox in your Grid. I have used the below method to find items in the visual tree, and it may do the trick for you.

    /// <summary>
    /// Will navigate down the VisualTree to find an element that is of the provided type.
    /// </summary>
    /// <typeparam name="T">The type of object to search for</typeparam>
    /// <param name="element">The element to start searching at</param>
    /// <returns>The found child or null if not found</returns>
    public static T GetVisualChild<T>(DependencyObject element) where T : DependencyObject
    {
        T child = default(T);
        int childrenCount = VisualTreeHelper.GetChildrenCount(element);

        for (int i = 0; i < childrenCount; i++) 
        {
            DependencyObject obj = VisualTreeHelper.GetChild(element, i);
            if (obj is T)
            {
                child = (T)obj;
                break;
            }
            else
            {
                child = GetVisualChild<T>(obj);
                if (child != null)
                    break;
            }
        }

        return child;
    }

Simply call GetVisualChild(myGrid) and it should return the first TextBox it comes to in myGrid.

Hope this helps.

Brian S
  • 5,675
  • 1
  • 22
  • 22
-1

If you only want to find resources at any hierarchy in the entire application then try this...

   var myResource = Application.Current.FindResource("MyResource");
WPF-it
  • 19,625
  • 8
  • 55
  • 71