WPF,这个现象怎么解释

WPF,这个现象如何解释
先前的问题,没得到好的答案,换成一个稍微简单点的。

<Window x:Class="WPF5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Name="button1" Content="Button" HorizontalAlignment="Left" Margin="90,39,0,0" VerticalAlignment="Top" Width="55" Height="64"/>
        <Button Name="button2" Content="Button" HorizontalAlignment="Left" Margin="270,103,0,0" VerticalAlignment="Top" Width="72" Height="69" Click="button2_Click"/>
    </Grid>
</Window>


public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TextBlock tt = new TextBlock() { Text = "张三" };
        button1.Content = tt;
        button2.Content = tt;
    }
    private void button2_Click(object sender, RoutedEventArgs e)
    {
        var c = button1.Content;
        MessageBox.Show((c as TextBlock).Text);
    }
}

WPF,这个现象怎么解释
上面的代码中,button1和button2的Content都是一个TextBlock ,显示效果如上图。
有两个问题:
1:为什么button1没有显示TextBlock ?我也知道一个TextBlock 不可能同时显示在两个不同的地方,在MSDN有这方面的详细解释吗?
2:单击button2,可以发现,其实button1的Content也是TextBlock ,其Text也是"张三",可是,为什么没有显示出来呢?
------解决思路----------------------
目测两个button的content需要两个textblock对象
你再new一个吧
------解决思路----------------------
问题出在button1和button2使用了同一个引用
            button1.Content = tt;
            button2.Content = tt;

逻辑上,tt是button1的子节点。因此,button1.Content可以拿到tt。
但是,从视觉上看,tt作为一个Visual只能是一个按键的子孙节点,因为Visual要有具体的位置和大小。
因此,在渲染下,tt只出现在button2下面。


视觉树:
Button
  ButtonChrome
    ContentPresenter
Button
  ButtonChrome
    ContentPresenter
      TextBlock     // tt在这里



private void button2_Click(object sender, RoutedEventArgs e)
{
    var c = button1.Content;
    MessageBox.Show((c as TextBlock).Text);

    StringBuilder sb = new StringBuilder("视觉树:\r\n");
    EnumVisual(button1.Parent as Visual, sb, 0);
    MessageBox.Show(sb.ToString());

    sb = new StringBuilder("逻辑树:\r\n");
    EnumLogical(button1.Parent, sb, 0);
    MessageBox.Show(sb.ToString());
}

private void EnumVisual(Visual v,  StringBuilder sb, int level)
{
    for(int i = 0; i < VisualTreeHelper.GetChildrenCount(v); i++)
    {
        Visual child = (Visual)VisualTreeHelper.GetChild(v, i);
        sb.AppendFormat("{0}{1}\r\n", new string(' ', level * 2), child.GetType().Name);
        EnumVisual(child, sb, level + 1);
    }
}

private void EnumLogical(DependencyObject o, StringBuilder sb, int level)
{
    foreach(object child in LogicalTreeHelper.GetChildren(o))
    {
        sb.AppendFormat("{0}{1}\r\n", new string(' ', level * 2), child);
        if (child is DependencyObject)
        {
            EnumLogical(child as DependencyObject, sb, level + 1);
        }
    }
}


------解决思路----------------------
如果嵌入image到多个element的话,会得到Specified Element is already Logical Child of another element的错误,应该是一个element只能有一个parent. 

大概看了下你的需求,可以试一试下面的解决方法:

1.  用Style来给Textblock的Text赋值,赋的值 是DynamicResource,在cs中指定。

   <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Text" Value="{DynamicResource MyResource}"></Setter>
        </Style>
    </Window.Resources>
    
    <Grid>
        <Button Name ="Button1" HorizontalAlignment="Left" Margin="89,77,0,0" VerticalAlignment="Top" Width="75" Click="Button1_Click">
            <TextBlock></TextBlock>
        </Button>
        <Button Name ="Button2" HorizontalAlignment="Left" Margin="89,131,0,0" VerticalAlignment="Top" Width="75">
            <TextBlock></TextBlock>
        </Button>

    </Grid>


2. 后台代码,初始化DynamicResource,点击按钮修改DynamicResource

        public MainWindow()
        {
            InitializeComponent();

            this.Resources["MyResource"] = "Test";
        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            this.Resources["MyResource"] = "Changed";
        }

------解决思路----------------------
这个应该跟Window窗口初始化有关,你如果把你的代码放到 loaded事件里 会发现 第二个button 没有内容!!!!这就比较诡异了。

个人理解是 跟button的Content属性与初始化顺序有关。  如果你使用以下代码就会同时显示:

TextBlock tt = new TextBlock() { Text = "张三" };
            button1.SetValue(ContentProperty, tt);
            button2.Content = tt.Text;

同时指定它的text为content或者指定其中一个。
------解决思路----------------------
引用:
还是感觉楼上的同志,没有说清楚诶。想知道MSDN上面有没有这种情况的解释

想知道为什么,为什么不自己去msdn上搜??你小学毕业,看不懂英文?
------解决思路----------------------
在WinForm中,一个控件实例同样不能被多个容器包含。

实际上,你应该绑定到数据上,同样的数据得到同样的显示;而不应该去关心是否用‘同一个控件’来显示。
比如改变你的代码:
        string tt = "张三" ;
        button1.Content = tt;
        button2.Content = tt;

------解决思路----------------------
Forty2的回答已经说明问题了。
+1
------解决思路----------------------
引用:
还是不清楚:button1的Content也是TextBlock ,其Text也是"张三",可是,为什么没有显示出来呢?


一个TextBlock只能有一个parent,你把它赋给button2的同时,就从button1中删除了。