How to get reference to element in resources, WPF?

2019-09-05 12:40发布

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!

3条回答
【Aperson】
2楼-- · 2019-09-05 13:33

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.

查看更多
Summer. ? 凉城
3楼-- · 2019-09-05 13:37

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? )

查看更多
家丑人穷心不美
4楼-- · 2019-09-05 13:40

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

   var myResource = Application.Current.FindResource("MyResource");
查看更多
登录 后发表回答