WPF FindName()查找命名注冊的元素


一、查找xaml中命名注冊的元素

        <Button x:Name="btn1" Content="顯示內容" 
                HorizontalAlignment="Left" Margin="25,115,0,0" VerticalAlignment="Top" Width="80" Height="60" Click="btn1_Click"/>
        <TextBox x:Name="txtOne" HorizontalAlignment="Left" Height="23" 
                 Margin="25,62,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="80"/>
//使用FindName() 查找
TextBox txtOne = this.FindName("txtOne") as TextBox;
if (txtOne != null)
{
    MessageBox.Show(txtOne.Text); //可以訪問到
}
TextBox txtTwo = btn1.FindName("txtOne") as TextBox;
if (txtTwo != null)
{
    MessageBox.Show(txtTwo.Text); //也可以訪問到
}

二、查找后台代碼命名注冊的元素

后台添加方式

TextBlock block = new TextBlock();
block.Text = "海上生明月";
panelOne.RegisterName("block1", block); //將block命名block1名稱注冊到panelOne上
panelOne.Children.Add(block);
//從當前窗口獲取,可以訪問到
TextBlock block1 = btn1.FindName("block1") as TextBlock;
if (block1 != null)
{
    MessageBox.Show(block1.Text);
}
//從Panel獲取,可以訪問到
TextBlock block2 = panelOne.FindName("block1") as TextBlock;
if (block2 != null)
{
    MessageBox.Show("panelOne:"+block2.Text);
}

注釋:元素名稱Name注冊, 不能重復。

-----------以下內容轉載:http://www.cnblogs.com/Clingingboy/archive/2010/11/29/1891253.html

預設置元素名字

WPF有兩種方式設置元素的Name

        <StackPanel x:Name="panel">
            <Label Name="name1" Content="Name1Label"/>
            <Label x:Name="name2" Content="Name2Label"/>
        </StackPanel>

這里我們的重點不在於討論Name和x:Name的區別,

Name是真正元素上的屬性,x:Name而則xaml(語法解析)的魔力,我們所看到的只能是表象.

不僅僅是注冊元素的名字

除了Element之外,其他類型也是可以的,如

            <Label>
                <Label.BorderBrush>
                    <SolidColorBrush x:Name="brushName"></SolidColorBrush>
                </Label.BorderBrush>
            </Label>

有些基本類型在xaml中無法設置,如String,Int類型等.但可以通過代碼設置

this.RegisterName("str", "Hello");

這里只有功能示例而已,但實際中千萬別這么做,本身不為此設計.

查找UserControl的元素

先定義一個UserControl

<UserControl x:Class="NameScopeDemo.MyUserControl"
             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">
    <Grid>
        <Button HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="btn">UserControl Button</Button>
    </Grid>
</UserControl>

在主窗體中使用UserControl

        <StackPanel x:Name="panel">
                   <local:MyUserControl x:Name="myControl"></local:MyUserControl>
        </StackPanel>

現在查找結果如下

image

若使用主窗體去無法查找到btn的話,但通過UserControl就可以.

在設計上將UI切分了,但卻給查找元素造成了麻煩了。

命名范圍(NameScope)

若以Code方式,添加方式則如下

uc = new MyUserControl();
var ns = new NameScope();
this.RegisterName("myControl", uc);
panel.Children.Add(uc);

為UserControl創建了一個獨立的命名范圍,想要查找MyUserControl的元素可以通過MyUserControl的級別的FindName來查找

模板取元素

            <ContentControl x:Name="cc">
                <ContentControl.ContentTemplate>
                    <DataTemplate>
                        <Button HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="btn">UserControl Button</Button>
                    </DataTemplate>
                </ContentControl.ContentTemplate>
            </ContentControl>

看到上面代碼,cc無法通過FindName查找到btn,只有模板的根元素才可以,這個根元素一般是ContentPresenter,所以當在模板內查找元素時,必須告訴其根元素

public Object FindName(
	string name,
	FrameworkElement templatedParent
)
那么首先我們就必須找到ContentPresenter,而只能通過視覺樹上面找,整體而言還是比較麻煩的,不知道為何內部API不封裝一下.
將模板內的元素名字注冊到父級
var ns = uc.GetValue(NameScope.NameScopeProperty) as IDictionary<string, object>;
var localNS = this.GetValue(NameScope.NameScopeProperty) as IDictionary<string, object>;
foreach (var n in ns)
{
    if (localNS.ContainsKey(n.Key))
    {
        this.RegisterName(n.Key, n.Value);
    }
}

首先獲取當前元素的NameScope,然后再將其注冊到父級命名范圍內以方便查找,值得注意的是模板內部的有些Name是固定的,如ScrollBar,其內部模板元素Name命名是有規定的,所以不要將其注冊在內.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM