长列表选择器可观察集合和可视化树 - 问题

本文关键字:可视化 问题 集合 列表 选择器 观察 | 更新日期: 2023-09-27 18:35:18



我举了一个简短的例子来说明我在哪里解决了一些问题。它们将 LongsListSelector 绑定到 ObservableCollection(无论是什么类型的项目)。我将长列表项模板设置为(例如)文本块,我还制作了三个按钮 - 将一个元素添加到集合,删除最后一个元素,以及搜索可视化树。代码不是那么长,所以我会在下面发布它(如果你想要整个例子,它在:http://sdrv.ms/163TYEG)。

XAML(标头除外):

    <phone:PhoneApplicationPage.Resources>
    <DataTemplate x:Key="ElementStyle">
        <TextBlock x:Name="elemBlck" Text="Element"/>
    </DataTemplate>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="30*"/>
        <RowDefinition Height="30*"/>
        <RowDefinition Height="30*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="70*"/>
        <ColumnDefinition Width="30*"/>
    </Grid.ColumnDefinitions>
    <Button x:Name="addBtn" Content="Add" Grid.Row="0" Grid.Column="1"/>
    <Button x:Name="delBtn" Content="Del" Grid.Row="1" Grid.Column="1"/>
    <Button x:Name="showBtn" Content="Show" Grid.Row="2" Grid.Column="1"/>       
    <phone:LongListSelector x:Name="phoneLLS" HorizontalAlignment="Left" Height="700" Margin="0" Grid.Row="0" 
                            VerticalAlignment="Top" Grid.RowSpan="3" Grid.Column="0" Width="300"
                            LayoutMode="Grid" GridCellSize="300,100" IsGroupingEnabled="False"
                            ItemTemplate="{StaticResource ElementStyle}" />
</Grid>

和 C#:

 public partial class MainPage : PhoneApplicationPage
 {
  private ObservableCollection<string> collection = new ObservableCollection<string>();
  public MainPage()
  {
     InitializeComponent();
     phoneLLS.ItemsSource = collection;
     addBtn.Click += addBtn_Click;
     delBtn.Click += delBtn_Click;
     showBtn.Click += showBtn_Click;
  }
  private void addBtn_Click(object sender, RoutedEventArgs e)
  {
     collection.Add("element");
  }
  private void delBtn_Click(object sender, RoutedEventArgs e)
  {
     collection.RemoveAt(collection.Count - 1);
  }
  private void showBtn_Click(object sender, RoutedEventArgs e)
  {
     List<TextBlock> controlList = new List<TextBlock>();
     SearchForControls<TextBlock>(phoneLLS, ref controlList);
  }
  private static void SearchForControls<T>(DependencyObject parent, ref List<T> controlList) where T : DependencyObject
  {
     int numberOfChildreen = VisualTreeHelper.GetChildrenCount(parent);
     for (int i = 0; i < numberOfChildreen; i++)
     {
        var child = VisualTreeHelper.GetChild(parent, i);
        if (child is T)
           controlList.Add((T)child);
        else SearchForControls<T>(child, ref controlList);
     }
  }
}

问题出在哪里?

  1. 当我按下"添加"按钮时,集合扩大了一个元素。好的,我看到它在 LLS 中添加了元素项目。但试着推动它更多。之后,只需按一下按钮即可出现几个元素?怎么了?集合扩大了一个元素,但 LLS 的填充速度要快得多。

  2. 与删除相同 - 它删除一个元素,但从 LLS 中有时会消失一组项目。

  3. 主要问题 - 在showBtn_Click的第二行切换断点。添加一些元素,尝试搜索可视化树(按显示按钮)。调试停止,在第二行之后,您会看到可视化树中元素的确切编号(与集合不同。计数)。第二个大惊喜 - 当你删除 en 元素,并再次搜索可视化树时,你会看到:集合减少了(这是正确的),一些元素从 LLS 中消失了(应该一个),而且!- 可视化树元素的数量没有变化(!怎么了?

    这些是某种错误吗?或者也许我不明白什么?

长列表选择器可观察集合和可视化树 - 问题

尝试将数据上下文设置为列表,并在 ItemsSource 属性中使用绑定。

Xaml:

<phone:LongListSelector ItemsSource={Binding} x:Name="phoneLLS"  HorizontalAlignment="Left" Height="700" Margin="0" Grid.Row="0" 
                        VerticalAlignment="Top" Grid.RowSpan="3" Grid.Column="0" Width="300"
                        LayoutMode="Grid" GridCellSize="300,100" IsGroupingEnabled="False"
                        ItemTemplate="{StaticResource ElementStyle}" />

代码隐藏:

public partial class MainPage : PhoneApplicationPage
{
   private ObservableCollection<string> collection = new ObservableCollection<string>();
   public MainPage()
   {
     InitializeComponent();
     phoneLLS.DataContext = collection;
     addBtn.Click += addBtn_Click;
     delBtn.Click += delBtn_Click;
     showBtn.Click += showBtn_Click;
   }
   ...
}

让我知道这是否有效。

我还做了一些进一步的研究 - 如果您使用 LLS 重新进入页面,一切都会正确更新 - 可视化树具有许多元素,例如集合。我修改了一个示例(http://sdrv.ms/169kRqI):

让我们Main_Page second_page

Xaml:

<phone:PhoneApplicationPage.Resources>
    <DataTemplate x:Key="ElementStyle">
        <TextBlock x:Name="elemBlck" Text="Element"/>
    </DataTemplate>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="30*"/>
        <RowDefinition Height="30*"/>
        <RowDefinition Height="30*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="70*"/>
        <ColumnDefinition Width="30*"/>
    </Grid.ColumnDefinitions>
    <Button x:Name="addBtn" Content="Add" Grid.Row="0" Grid.Column="1"/>
    <Button x:Name="delBtn" Content="Del" Grid.Row="1" Grid.Column="1"/>
    <Button x:Name="showBtn" Content="Show" Grid.Row="2" Grid.Column="1"/>
    <phone:LongListSelector x:Name="phoneLLS" HorizontalAlignment="Left" Height="700" Margin="0" Grid.Row="0" 
                            VerticalAlignment="Top" Grid.RowSpan="3" Grid.Column="0" Width="300"
                            LayoutMode="Grid" GridCellSize="300,100" IsGroupingEnabled="False"
                            ItemTemplate="{StaticResource ElementStyle}" ItemsSource="{Binding}"/>
</Grid>

代码隐藏:

public partial class second_page : PhoneApplicationPage
{
  public second_page()
  {
     InitializeComponent();
     phoneLLS.DataContext = MainPage.collection;
     addBtn.Click += addBtn_Click;
     delBtn.Click += delBtn_Click;
     showBtn.Click += showBtn_Click;
  }
  private void addBtn_Click(object sender, RoutedEventArgs e)
  {
     MainPage.collection.Add("element");
  }
  private void delBtn_Click(object sender, RoutedEventArgs e)
  {
     MainPage.collection.RemoveAt(MainPage.collection.Count - 1);
  }
  private void showBtn_Click(object sender, RoutedEventArgs e)
  {
     List<TextBlock> controlList = new List<TextBlock>();
     SearchForControls<TextBlock>(phoneLLS, ref controlList);
  }
  private static void SearchForControls<T>(DependencyObject parent, ref List<T> controlList) where T : DependencyObject
  {
     int numberOfChildreen = VisualTreeHelper.GetChildrenCount(parent);
     for (int i = 0; i < numberOfChildreen; i++)
     {
        var child = VisualTreeHelper.GetChild(parent, i);
        if (child is T)
           controlList.Add((T)child);
        else SearchForControls<T>(child, ref controlList);
     }
  }
}

和Main_Page - 仅导航:

Xaml:

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Button x:Name="goToPage" Content="SecondPage" Width="Auto" Height="Auto"
            HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

代码隐藏:

public partial class MainPage : PhoneApplicationPage
{
  public static ObservableCollection<string> collection = new ObservableCollection<string>();
  public MainPage()
  {
     InitializeComponent();
     goToPage.Click+=goToPage_Click;
  }
  private void goToPage_Click(object sender, RoutedEventArgs e)
  {
     NavigationService.Navigate(new Uri("/second_page.xaml", UriKind.Relative));
  }
}

只需尝试在重新进入页面和不重新进入页面的情况下执行相同的操作:

  1. 例如添加 3 个元素,调试器在showBtn_Click的第二行切换断点并单击 buton - 它将显示 6 个元素!除了回去,不要碰任何东西。

  2. 重新进入第二页 - 您将找到正确的 LLS - 包含 3 个元素,当您单击带有断点的 showBtn 时,您将在可视化树中看到 3 个元素。

    有人试过这个吗?