【问题标题】:Can't get ListViewItem when using custom object使用自定义对象时无法获取 ListViewItem
【发布时间】:2016-06-07 02:39:45
【问题描述】:

我找了又找,但找不到答案。

C# 和 WPF,我有一个包含 5 列的 ListView,每列都有一个 TextBox。

我的自定义类

public class SomeThing
{
    public String field1 { get; set; }
    public String field2 { get; set; }
    public String field3 { get; set; }
    public String field4 { get; set; }
    public String field5 { get; set; }
}

我的添加代码

SomeThing item = new SomeThing();
lstItems.Items.Add(item);

我的按键密码

private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if(e.Key == Key.Return || e.Key == Key.Tab)
        {
            TextBox tb = (TextBox)sender;
            Grid grid = (Grid)tb.Parent;                

            if (tb.Tag.Equals("Price"))
            {
                if(lstItems.Items.Count <= lstItems.SelectedIndex + 1) {                     
                    SomeThing item = new SomeThing();
                    lstItems.Items.Add(item);                        
                }

                lstItems.SelectedIndex = lstItems.SelectedIndex + 1;                   

                ListViewItem selectedItem = (ListViewItem)lstItems.ItemContainerGenerator.ContainerFromItem(this.lstItems.SelectedItem);

                    e.Handled = true;
            }                               

        }
    }

但是

ListViewItem selectedItem = (ListViewItem)lstItems.ItemContainerGenerator.ContainerFromItem(this.lstItems.SelectedItem);

始终为空,

this.lstItems.SelectedItem 

只是实例“SomeThing”的一个对象。

如何获取 ListView 容器?

如何将 TextBox 聚焦在新选定的行上?

请帮忙

【问题讨论】:

  • 您是否尝试将其投射到您的自定义类中? (Something)this.lstItems.SelectedItem
  • @jpaugh78 这是我在调试时进行检查的时候。我无法将其转换为 ListViewItem,因为它的类型为 SomeThing
  • 好吧,我没有意识到 ListView 的工作方式与我通常使用的控件有一点不同。我发现了一个可能对你有帮助的线程:stackoverflow.com/questions/17857367/…

标签: c# wpf listview listviewitem


【解决方案1】:

很可能您正试图从ItemContainerGenerator 获取在您请求时尚未生成的内容。将项目添加到 ItemsControlListView 是其子类)不会立即为该项目创建容器。存在延迟。

这并不是处理ItemsControl 实例的理想方式。它们实际上是围绕与 MVVM 设计模式一起使用而设计的。但是,如果您出于某种原因需要以这种方式使用它,则需要注意 ItemContainerGenerator 上的 Status 属性和关联的 StatusChanged 事件。

所以,大致是这样的:

    if (myItemsControlInstance.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
    {
        // You should be able to get the container using ContainerFromItem
    }
    else
    {
        // You will have to wait
        myItemsControlInstance.ItemContainerGenerator.StatusChanged += myItemsControlInstance_StatusChanged;
    }

...

void myItemsControlInstance_StatusChanged(object sender, EventArgs e)
{
    if (myItemsControlInstance.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
    {
        myItemsControlInstance.ItemContainerGenerator.StatusChanged -= myEventHandler;
        // You should be able to get the container now using ContainerFromItem.
        // However, layout hasn't been performed on it yet at this point, so there is
        // no guarantee that the item is in good condition to be messed with yet.
        LayoutUpdated += app_LayoutUpdated;
    }
}

void app_LayoutUpdated(object sender, EventArgs e)
{
    LayoutUpdated -= app_LayoutUpdated;
    if (myItemsControlInstance.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
    {
        // Now, you can finally get the container using ContainerFromItem and do something with it.
    }
    else
    {
        // It looks like more items needed to be generated...
        myItemsControlInstance.ItemContainerGenerator.StatusChanged += myItemsControlInstance_StatusChanged;
    }
}

尽管像这样直接使用ItemContainerGenerator 时,您还需要注意一些事项:

  • 生成器上的Status 可以是Error。您可能想检查一下,尽管我从未见过这种情况。
  • 如果ItemsControl 使用虚拟化面板来包含项目,则您可能正在尝试访问不在视图中因此不存在的项目。您可以通过设置ItemsPanel 属性来覆盖用于不虚拟化的面板类型,例如StackPanel 而不是VirtualizingStackPanel,或者您可以确保在开始进程之前以某种方式将项目滚动到视图中(即一个完全独立的主题)。

我的建议是切换到 MVVM 模型并阅读如何以更自然的方式使用 ItemsControl,因为这样做既复杂又容易出错。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多