我有一个ContentControl,我想在某些事件中更改它的ContentTemplate。我想在加载ContentTemplate中的控件时添加一些值(文本到TextBox)。 但是,我发现应用新的ContentTemplate(在加载新模板的所有控件方面)不是直接更改属性ContentTemplate后。是否有一些事件显示新的ContentTemplate已完全应用?
var cp = GetVisualChild<ContentPresenter>(myContentControl);
var txt = myContentControl.ContentTemplate.FindName("Path_Cover", cp) as TextBox;
txt.Text = "test";
GetVisualChild
private T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
我得到了一个错误:
myContentControl.ContentTemplate = newContentTemplate;
// at this line controls of new template are not loaded!
我这条线测试后,通过添加该代码
This operation is valid only on elements that have this template applied.
有一些事件显示新的ContentTemplat e是完全适用的?
编辑1
@eran 我试图onApplyTemplate
public override void OnApplyTemplate()
{
var cp = GetVisualChild<ContentPresenter>(Content_Option);
var txt = Content_Option.ContentTemplate.FindName("Path_Cover", cp) as TextBox;
txt.Text = "test";
}
,但得到的错误:
Object reference not set to an instance of an object.
EDIT 2
这种 “肮脏” 的方法非常有效:
myContentControl.ContentTemplate = newContentTemplate;
System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(0.000001);
timer.Tick += new EventHandler(delegate(object s, EventArgs a)
{
timer.Stop();
var cp = GetVisualChild<ContentPresenter>(Content_Option);
var txt = Content_Option.ContentTemplate.FindName("Path_Cover", cp) as TextBox;
txt.Text = "teSt";
});
timer.Start();
能有人帮助我实现更多的 “干净”(设备专业)的方式:)
编辑同一个结果3
我情景是,我有一个TreeView(左侧)作为菜单,Grid(右侧)作为ContentControl的显示。 TreeView有一些节点。每个节点都有它自己的DataTemplate。每次点击一个TreeView节点时,都会将DataTemplate设置为ContentControl,并从数据库中设置一个值(例如Path_Cover.Text)。 布局或多或少像Windows资源管理器。
嗯,这是所有必要的代码:
XAML
<UserControl.Resources>
<DataTemplate x:Key="General">
<StackPanel>
<DockPanel>
<TextBlock Text="Cover"/>
<TextBox Name="Path_Cover"/>
</DockPanel>
<DockPanel>
<TextBlock Text="Slide"/>
<TextBox Name="Path_Slide"/>
</DockPanel>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Appearance">
<StackPanel>
<DockPanel>
<TextBlock Text="Cover"/>
<TextBox Name="Path_Cover"/>
</DockPanel>
<DockPanel>
<Button Content="Get Theme"/>
<TextBox Name="Txt_Theme"/>
</DockPanel>
</StackPanel>
</DataTemplate>
<UserControl.REsources>
<Grid>
<ContentControl Name="myContentControl"/>
</Grid>
代码隐藏
private void TreeMenu_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
myContentControl.ContentTemplate =(DataTemplate)this.Resources[Tree_Menu.SelectedItem.ToString()];
System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(0.000001);
timer.Tick += new EventHandler(delegate(object s, EventArgs a)
{
timer.Stop();
switch (Tree_Menu.SelectedItem.ToString())
{
case "General":
var cp = GetVisualChild<ContentPresenter>(Content_Option);
var txt = Content_Option.ContentTemplate.FindName("Path_Cover", cp) as TextBox;
txt.Text = "test";
txt = Content_Option.ContentTemplate.FindName("Path_Slide", cp) as TextBox;
txt.Text = "test";
break;
case "Appearance":
var cp = GetVisualChild<ContentPresenter>(Content_Option);
var txt = Content_Option.ContentTemplate.FindName("Txt_Theme", cp) as TextBox;
txt.Text = "test";
break;
}
});
timer.Start();
}
我只需要 “移动” 内部定时器的代码.tick事件处理程序添加到在DataTemplate/ContentTemplate完全应用后触发的一些新事件。
在OnApplayTemplate之后调用OnLoad或OnLoadData 检查msdn –
@eran Onload事件只触发一次。我想要每次更改ContentTemplate时触发的事件。 – Reyn