Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从listbox获取Listboxitem_C#_Wpf_Listbox - Fatal编程技术网

C# 从listbox获取Listboxitem

C# 从listbox获取Listboxitem,c#,wpf,listbox,C#,Wpf,Listbox,嗨,这应该很简单,但我不知道我做错了什么。我在互联网上到处寻找,看到有人做了这项工作,即使是遵循了MSDN的教程,仍然没有任何东西对我有效 我想迭代一个ListBox,并获取ListBoxItems,这样我就可以找到我添加到其中的DataTemplate 这是我的密码 private void SetListBoxDataTemplate(ListBox MyListBox) { try { foreach (CustomDataTemplateObject dataobject

嗨,这应该很简单,但我不知道我做错了什么。我在互联网上到处寻找,看到有人做了这项工作,即使是遵循了MSDN的教程,仍然没有任何东西对我有效

我想迭代一个ListBox,并获取ListBoxItems,这样我就可以找到我添加到其中的DataTemplate

这是我的密码

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层中使用

我也高度推荐