C# 从listbox获取Listboxitem
嗨,这应该很简单,但我不知道我做错了什么。我在互联网上到处寻找,看到有人做了这项工作,即使是遵循了MSDN的教程,仍然没有任何东西对我有效 我想迭代一个ListBox,并获取ListBoxItems,这样我就可以找到我添加到其中的DataTemplate 这是我的密码C# 从listbox获取Listboxitem,c#,wpf,listbox,C#,Wpf,Listbox,嗨,这应该很简单,但我不知道我做错了什么。我在互联网上到处寻找,看到有人做了这项工作,即使是遵循了MSDN的教程,仍然没有任何东西对我有效 我想迭代一个ListBox,并获取ListBoxItems,这样我就可以找到我添加到其中的DataTemplate 这是我的密码 private void SetListBoxDataTemplate(ListBox MyListBox) { try { foreach (CustomDataTemplateObject dataobject
private void SetListBoxDataTemplate(ListBox MyListBox)
{
try
{
foreach (CustomDataTemplateObject dataobject in MyListBox.Items)
{
ListBoxItem lbi = (ListBoxItem)(MyListBox.ItemContainerGenerator.ContainerFromItem(dataobject));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(lbi);
DataTemplate dt = myContentPresenter.ContentTemplate;
TextBlock tb = (TextBlock)dt.FindName("ListBoxItemTextBlock1", myContentPresenter);
ComboBox cb = (ComboBox)dt.FindName("ListBoxItemComboBox1", myContentPresenter);
tb.Text = dataobject.Text;
cb.ItemsSource = dataobject.ListColors;
}
}
catch (Exception ex)
{
MessageBox.Show(""+ex);
}
}
private void SetListBoxDataTemplate(ListBox MyListBox)
{
尝试
{
foreach(MyListBox.Items中的CustomDataTemplateObject数据对象)
{
ListBoxItem lbi=(ListBoxItem)(MyListBox.ItemContainerGenerator.ContainerFromItem(dataobject));
ContentPresenter myContentPresenter=FindVisualChild(lbi);
DataTemplate dt=myContentPresenter.ContentTemplate;
TextBlock tb=(TextBlock)dt.FindName(“ListBoxItemTextBlock1”,myContentPresenter);
ComboBox cb=(ComboBox)dt.FindName(“ListBoxItemComboBox1”,myContentPresenter);
tb.Text=dataobject.Text;
cb.ItemsSource=dataobject.ListColor;
}
}
捕获(例外情况除外)
{
MessageBox.Show(“+ex”);
}
}
XAML如下所示:
<DataTemplate x:Key="ListBoxItemDataTemplate1">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1 1 0 1" MinWidth="50">
<TextBlock Name="ListBoxItemTextBlock1" Background="{Binding ElementName=ListBoxItemComboBox1, Path=SelectedValue}" >
</TextBlock>
</Border>
<ComboBox Name="ListBoxItemComboBox1" />
</StackPanel>
</DataTemplate>*
<StackPanel>
<ListBox Name="ListBoxTest1" ItemTemplate="{DynamicResource ListBoxItemDataTemplate1}" />
</StackPanel>
<DataTemplate x:Key="ListBoxItemDataTemplate1">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1 1 0 1" MinWidth="50">
<TextBlock Text="{Binding Text}" Background="{Binding ElementName=ListBoxItemComboBox1, Path=SelectedValue}" >
</TextBlock>
</Border>
<ComboBox ItemsSource="{Binding ListColors}" />
</StackPanel>
</DataTemplate>*
*
我尝试将itemtemplate设置为static,以查看它是否有效,并且在填充ListBoxs后,将调用我从代码隐藏中调用的方法
我的dataobject不是空的,但是当我调用代码中的行时,我的lbi最终是空的
有什么建议吗?提前谢谢
第一次更新
只有在调用构造函数中的方法时才会出现此问题,因此可能是因为它尚未初始化完整的组元素部分。然而,我想尽快做到这一点。我是否被迫在WindowLoaded事件中执行此操作
第二次更新
代码更新后,Rachel的答案用于迭代我的ListBoxItems,但是Listbox没有完全呈现,因为此时我无法访问Datatemplate。因此MyListBox_GeneratorsStatusChanged无法解决此问题,但它确实获得了ListBoxItems。您混淆了两个作业,并将它们混合到一个作业中。首先,访问
ListBoxItem
:
private void SetListBoxDataTemplate(ListBox MyListBox)
{
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
}
}
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
ContentPresenter presenter = FindVisualChild<ContentPresenter>(listBoxItem);
DataTemplate dataTemplate = presenter.ContentTemplate;
if (dataTemplate != null)
{
// Do something with dataTemplate here
}
}
现在,您可以从ListBoxItem
获取DataTemplate
:
private void SetListBoxDataTemplate(ListBox MyListBox)
{
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
}
}
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
ContentPresenter presenter = FindVisualChild<ContentPresenter>(listBoxItem);
DataTemplate dataTemplate = presenter.ContentTemplate;
if (dataTemplate != null)
{
// Do something with dataTemplate here
}
}
foreach(MyListBox.Items中的ListBoxItem ListBoxItem)
{
ContentPresenter-presenter=FindVisualChild(listBoxItem);
DataTemplate DataTemplate=presenter.ContentTemplate;
if(dataTemplate!=null)
{
//在这里使用dataTemplate执行一些操作
}
}
FindVisualChild
方法可以在MSDN的页面中找到
更新>>>
要回答您的编辑,是的,构造函数将太早,无法尝试访问这些
DataTemplate
s,因为框架届时不会将它们应用于所有对象。最好使用来执行这类操作,因为这是初始化控件后可以调用的第一个事件。您混淆了两个作业,并将它们混合到一个作业中。首先,访问ListBoxItem
:
private void SetListBoxDataTemplate(ListBox MyListBox)
{
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
}
}
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
ContentPresenter presenter = FindVisualChild<ContentPresenter>(listBoxItem);
DataTemplate dataTemplate = presenter.ContentTemplate;
if (dataTemplate != null)
{
// Do something with dataTemplate here
}
}
现在,您可以从ListBoxItem
获取DataTemplate
:
private void SetListBoxDataTemplate(ListBox MyListBox)
{
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
}
}
foreach (ListBoxItem listBoxItem in MyListBox.Items)
{
ContentPresenter presenter = FindVisualChild<ContentPresenter>(listBoxItem);
DataTemplate dataTemplate = presenter.ContentTemplate;
if (dataTemplate != null)
{
// Do something with dataTemplate here
}
}
foreach(MyListBox.Items中的ListBoxItem ListBoxItem)
{
ContentPresenter-presenter=FindVisualChild(listBoxItem);
DataTemplate DataTemplate=presenter.ContentTemplate;
if(dataTemplate!=null)
{
//在这里使用dataTemplate执行一些操作
}
}
FindVisualChild
方法可以在MSDN的页面中找到
更新>>>
要回答您的编辑,是的,构造函数将太早,无法尝试访问这些
DataTemplate
s,因为框架届时不会将它们应用于所有对象。最好使用来执行这类操作,因为这是初始化控件后可以调用的第一个事件。WPF的主线程以不同的速度运行项目。构造函数中运行的代码都以Normal
优先级运行,而呈现ListBox
及其项则以Render
优先级运行,这是在所有Normal
优先级操作完成后发生的
这意味着您的整个构造函数(包括SetListBoxDataTemplate()
)在您的ListBox
被渲染和生成项之前就已经运行了
如果要在生成项目后运行某些代码,请使用事件
你用这种方法到底想达到什么目的?这对于WPF来说有点不寻常,而且可能有更好的WPF方式来完成您的任务
根据问题中添加的新代码进行更新
设置文本
和项目资源
属性的更好方法是使用WPF的数据绑定
您的数据模板应如下所示:
<DataTemplate x:Key="ListBoxItemDataTemplate1">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1 1 0 1" MinWidth="50">
<TextBlock Name="ListBoxItemTextBlock1" Background="{Binding ElementName=ListBoxItemComboBox1, Path=SelectedValue}" >
</TextBlock>
</Border>
<ComboBox Name="ListBoxItemComboBox1" />
</StackPanel>
</DataTemplate>*
<StackPanel>
<ListBox Name="ListBoxTest1" ItemTemplate="{DynamicResource ListBoxItemDataTemplate1}" />
</StackPanel>
<DataTemplate x:Key="ListBoxItemDataTemplate1">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1 1 0 1" MinWidth="50">
<TextBlock Text="{Binding Text}" Background="{Binding ElementName=ListBoxItemComboBox1, Path=SelectedValue}" >
</TextBlock>
</Border>
<ComboBox ItemsSource="{Binding ListColors}" />
</StackPanel>
</DataTemplate>*
此外,ListBoxItem
后面的DataContext
是绑定到ListBox.ItemsSource
的集合中的项,它基于您的代码应该是CustomDataTemplateObject
。这允许来自DataTemplate的绑定工作
如果您是WPF新手,并且很难理解DataContext
的工作原理,我建议您阅读我的这篇文章:
总之,WPF对应用程序有两层:UI层和数据层(DataContext
)。当您执行如上所述的基本绑定时,您正在将数据从数据层拉入UI层
因此,您的ListBoxItem
有一个数据层CustomDataTemplateObject
,以及TextBlock.Text
和ComboBox.ItemsSource
绑定正在从数据层中提取数据,以便在UI层中使用
我也高度推荐