gpt4 book ai didi

wpf - 是否有一些事件显示新的 ContentTemplate 已完全应用?

转载 作者:行者123 更新时间:2023-12-04 08:45:22 26 4
gpt4 key购买 nike

我有一个 ContentControl,我想在某些事件中更改它的 ContentTemplate。我想在加载 ContentTemplate 中的控件时添加一些值(文本到 TextBox)。
但是,我发现在更改属性 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";

获取视觉 child
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.



是否有一些事件显示新的 ContentTemplate 已完全应用?

编辑 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.



编辑 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();
}

我只需要将 timer.tick 事件处理程序中的代码“移动”到一些在 DataTemplate/ContentTemplate 完全应用后触发的新事件。

最佳答案

我知道这是一个很老的问题,但我一直在寻找答案并发明了一个答案,认为这是一个分享它的好地方。

我只是从标准的 ContentPresenter 创建了我自己的 ContentPresenter 类:

public class ContentPresenter : System.Windows.Controls.ContentPresenter {

#region RE: ContentChanged
public static RoutedEvent ContentChangedEvent = EventManager.RegisterRoutedEvent("ContentChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ContentPresenter));
public event RoutedEventHandler ContentChanged {
add { AddHandler(ContentChangedEvent, value); }
remove { RemoveHandler(ContentChangedEvent, value); }
}
public static void AddContentChangedHandler(UIElement el, RoutedEventHandler handler) {
el.AddHandler(ContentChangedEvent, handler);
}
public static void RemoveContentChangedHandler(UIElement el, RoutedEventHandler handler) {
el.RemoveHandler(ContentChangedEvent, handler);
}
#endregion

protected override void OnVisualChildrenChanged(System.Windows.DependencyObject visualAdded, System.Windows.DependencyObject visualRemoved) {
base.OnVisualChildrenChanged(visualAdded, visualRemoved);
RaiseEvent(new RoutedEventArgs(ContentChangedEvent, this));
}
}

我希望这可以帮助那些正在寻找一个简单的解决方案来解决 ContentPresenter 设计中这种明显疏忽的人。

关于wpf - 是否有一些事件显示新的 ContentTemplate 已完全应用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13494660/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com