在我的Windows Phone 8.1应用程序中,我有一个列表框,当我最初加载我要在列表框中显示的所有内容时,一切都很好。但滚动后,某些元素将显示不正确。这似乎是完全随机的。
前面提到的列表框在xaml中是这样的:
<ListBox Name="MainPage_List" Grid.Column="0" Background="#EDEDED" >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Components:MyUserControl />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
如您所见,其datatemplate链接到usercontrol。在这个UserControl中,我有一个DataContextChanged事件。看起来像这样:
private void DataContextChanged(object sender, object e)
{
if (mySource == null)
{
mySource = DataContext as Message;
}
if (mySource != null)
{
if (mySource.Source_Type == SourceTypes.Type1)
{
MyGrid.Visibility = Visibility.Collapsed;
MyOtherGrid.Visibility = Visibility.Visible;
}
else if (mySource.Source_Type == SourceTypes.Type2)
{
MyOtherGrid.Visibility = Visibility.Collapsed;
MyGrid.Visibility = Visibility.Visible;
}
}
}
我在这里检查多个类型和变量,并根据我设置其他可见的东西或加载其他图像。这很好用。但是,当滚动列表时,有时会显示某些元素的不同之处。即使我确保决定显示哪些元素的代码不再使用。
列表的来源是一个自定义类,它使用一个来自INotifyPropertyChanged的自定义类从ObservableCollection中继承。
有谁知道我在做错了什么?或者为什么会发生这种情况以及如何解决这个问题?
答案 0 :(得分:1)
这可能是虚拟化的结果。 如果您的列表足够长,则可以重复使用其中的项目。 想象一下,你有一个包含1000个项目的列表,但是列表框只有30个控件实例,当你向上和向下滚动时会重复使用它们。 如果是这种情况,您将看到错误的行为重复X项。
为了解决这个问题,我建议您不要使用DataContextChanged,而应该将属性公开为DependencyProperty。
在您的数据模板中,绑定到此属性,这将为您提供帮助。
public bool ShowMyGrid
{
get { return (bool)GetValue(ShowMyGridProperty); }
set { SetValue(ShowMyGridProperty, value); }
}
public static readonly DependencyProperty ShowMyGridProperty =
DependencyProperty.Register("ShowMyGrid", typeof(bool), typeof(MyUserControl1), new UIPropertyMetadata(false, ShowMyGridCallback));
static void ShowMyGridCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var myControl = d as MyUserControl1;
bool newVal = (bool)e.NewValue;
if (newVal)
{
myControl.MyGrid.Visibility = Visibility.Collapsed;
myControl.MyOtherGrid.Visibility = Visibility.Visible;
}
else
{
myControl.MyGrid.Visibility = Visibility.Visible;
myControl.MyOtherGrid.Visibility = Visibility.Collapsed;
}
}
答案 1 :(得分:1)
经过与WereWolfBoy的一些讨论后,我们发现了问题。
它与ListBox的默认ItemsPanel有关,它是VirtualizingStackPanel。它重用ListBox的ItemTemplate中的控件,并在必要时更改其DataContext以显示不同的项。与普通的StackPanel不同,它不会为不同的项目创建单独的控件。
要使其工作,DataContext更改时必须刷新项目。这是实际问题。因为这段代码:
if (mySource == null)
{
mySource = DataContext as Message;
}
DataContext实际上只加载了一次,后续更改不会影响UI。删除if
并在每次更改时获取DataContext都会解决问题。