いくつかのイベントでContentTemplateを変更したいContentControlがあります。 ContentTemplateのコントロールがロードされたときに、いくつかの値(TextBoxにテキスト)を追加します。 しかし、新しいContentTemplateが、プロパティContentTemplateを変更した後ではなく、新しいテンプレートのすべてのコントロールをロードするという点では、直接適用されないことがわかりました。新しいContentTemplateが完全に適用されたことを示すイベントはありますか?
私はその行の後に追加このコードによってテストmyContentControl.ContentTemplate = newContentTemplate;
// at this line controls of new template are not loaded!
:
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;
}
私はエラーを持っている:
This operation is valid only on elements that have this template applied.
は、いくつかのイベントがありますその新しいContentTemplatを示すeは完全に適用されますか? @eran
EDIT 1
私は
public override void OnApplyTemplate()
{
var cp = GetVisualChild<ContentPresenter>(Content_Option);
var txt = Content_Option.ContentTemplate.FindName("Path_Cover", cp) as TextBox;
txt.Text = "test";
}
onApplyTemplate
試みたが、エラーが発生しました: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();
誰かが(プロフェッショナル)の方法より "クリーン" と同じ結果を達成するために私を助けることができます:)
EDIT 3
マイシナリオは、私はContentControlのための表示としてメニューとグリッド(右側)のTreeView(左側)を持っています。 TreeViewにはいくつかのノードがあります。各ノードには独自のDataTemplateがあります。 TreeViewノードがクリックされるたびに、DataTemplateがContentControlに設定され、データベースから値(例:Path_Cover.Text)が設定されます。 レイアウトは、Windowsエクスプローラとほぼ同じです。
まあ、これは必要なすべてのコードです:
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();
}
の後ろ
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>
コード私はちょうどタイマー内のコード "移動" に必要です.tickイベントハンドラを、DataTemplate/ContentTemplateが完全に適用された後に起動する新しいイベントに追加します。
OnApplayTemplateの後にOnLoadまたはOnLoadDataが呼び出されます。 check msdn –
@eran Onloadイベントは1回だけ発生します。 ContentTemplateを変更するたびに発生するイベントが必要です。 – Reyn