我有一个简单的ListView,没有项目模板和SelectionChanged事件设置:
<ListView x:Name="list1" HorizontalAlignment="Left"
Height="556"
Margin="209,93,0,0"
VerticalAlignment="Top"
Width="1033"
SelectionChanged="list1_SelectionChanged" />
private void list1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var container = (sender as ListView).ContainerFromItem(e.AddedItems.First());
var presenter = VisualTreeHelper.GetChild(container, 0);
}
我还有一个测试类如下:
class Test
{
public string FirstName { get; set; }
public string Surname { get; set; }
}
现在在页面的构造函数中,我有以下代码创建一个测试项的ObservableCollection,添加一些,然后将其设置为ListView的ItemSource:
ObservableCollection<Test> testCollection;
public MainPage()
{
this.InitializeComponent();
testCollection = new ObservableCollection<Test>();
testCollection.Add(new Test { FirstName = "Bob", Surname = "Smith1" });
testCollection.Add(new Test { FirstName = "Bob", Surname = "Smith2" });
testCollection.Add(new Test { FirstName = "Bob", Surname = "Smith3" });
list1.ItemsSource = testCollection;
}
现在,当我在列表中选择一个项目并激活SelectionChanged事件时,容器变量按预期包含ListViewItem。
现在,我在表单上也有按钮,这里是按钮点击事件:
private void Button_Click(object sender, RoutedEventArgs e)
{
testCollection.Add(new Test { FirstName = "Bob", Surname = "Smith4" });
list1.SelectedIndex = list1.Items.Count - 1;
}
最后一行选择新项目并触发SelectionChanged事件,但这次容器变量为null。
有人可以告诉我为什么这是空的,我该如何解决这个问题?
由于
答案 0 :(得分:10)
我可以告诉你。
您在这里遇到的是时间问题。您认为可以多快将项目添加到集合中?快 - 只有一两毫秒。您认为ListView
设置SelectedItem
属性并引发SelectionChanged
事件需要多快?快 - 一毫秒或两秒。但是,您认为ListView
在屏幕上实际呈现新项目并为其生成容器需要多快?很长一段时间 - 比如10到100毫秒,具体取决于DataTemplate
的复杂程度。
我意识到你的测试没有设置ItemTemplate
,我假设你这样做是假设它会渲染得更快 - 也许是即时的。但每个DataTemplate
都有一个默认ItemsControl
。而且,即使像内置的DataTemplate
这样的简单async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var items = Enumerable.Range(1, 10)
.Select(x => new Item { FirstName = "Bob", LastName = "Smith" + x.ToString() });
var list = new ObservableCollection<Item>(items);
MyListView.ItemsSource = list;
var item = new Item { FirstName = "Jerry", LastName = "Nixon" };
list.Add(item);
await Task.Delay(1000);
MyListView.SelectedItem = item;
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
System.Diagnostics.Debug.Assert(e.AddedItems.Any());
var listview = sender as ListView;
var container = listview.ContainerFromItem(e.AddedItems.First());
System.Diagnostics.Debug.Assert(container != null);
var presenter = VisualTreeHelper.GetChild(container, 0);
System.Diagnostics.Debug.Assert(presenter != null);
}
,仍然需要花费更多的时间来推进单个C#线。
这段代码将说明我的意思:
Delay
请注意
Loaded
代码;这就是它的工作原理。
希望您简化了问题,这就是您在代码隐藏中而不是在视图模型中进行工作的原因。精细。首先,请确保在ListView
中处理此类逻辑,以确保您的{{1}}可用。然后,再次在视图模型中执行此操作。
所以,我已经回答了你的问题。为什么?因为时间安排。
在我看来,这可能都是通过一个简单的视图模型来解决的,但话说回来,我只知道你的情况。也许有一些我没有看到的东西。
祝你好运!