WPF,这个现象怎么解释
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下面。
------解决思路----------------------
如果嵌入image到多个element的话,会得到Specified Element is already Logical Child of another element的错误,应该是一个element只能有一个parent.
大概看了下你的需求,可以试一试下面的解决方法:
1. 用Style来给Textblock的Text赋值,赋的值 是DynamicResource,在cs中指定。
2. 后台代码,初始化DynamicResource,点击按钮修改DynamicResource
------解决思路----------------------
这个应该跟Window窗口初始化有关,你如果把你的代码放到 loaded事件里 会发现 第二个button 没有内容!!!!这就比较诡异了。
个人理解是 跟button的Content属性与初始化顺序有关。 如果你使用以下代码就会同时显示:
同时指定它的text为content或者指定其中一个。
------解决思路----------------------
想知道为什么,为什么不自己去msdn上搜??你小学毕业,看不懂英文?
------解决思路----------------------
在WinForm中,一个控件实例同样不能被多个容器包含。
实际上,你应该绑定到数据上,同样的数据得到同样的显示;而不应该去关心是否用‘同一个控件’来显示。
比如改变你的代码:
string tt = "张三" ;
button1.Content = tt;
button2.Content = tt;
------解决思路----------------------
Forty2的回答已经说明问题了。
+1
------解决思路----------------------
一个TextBlock只能有一个parent,你把它赋给button2的同时,就从button1中删除了。
先前的问题,没得到好的答案,换成一个稍微简单点的。
<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);
}
}
上面的代码中,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上搜??你小学毕业,看不懂英文?
------解决思路----------------------
在WinForm中,一个控件实例同样不能被多个容器包含。
实际上,你应该绑定到数据上,同样的数据得到同样的显示;而不应该去关心是否用‘同一个控件’来显示。
比如改变你的代码:
string tt = "张三" ;
button1.Content = tt;
button2.Content = tt;
------解决思路----------------------
Forty2的回答已经说明问题了。
+1
------解决思路----------------------
一个TextBlock只能有一个parent,你把它赋给button2的同时,就从button1中删除了。