MapsItemControl 和 ObservableCollection 行为

MapsItemControl and ObservableCollection behaviour

我有下一个 MapsItemControl 模板可以在地图上显示许多 pins/items。它绑定到 ObservableCollection,因为我希望它们被过滤以通过不同的选项显示或隐藏。这是地图控件中 MapsItemControl 的 XAML 代码。

<Maps:MapItemsControl x:Name="mapSpotsItems">
    <Maps:MapItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel x:Name="spotPin" Visibility="{Binding isVisible}"
                        Maps:MapControl.Location="{Binding geopoint}" Tag="{Binding ID}" ToolTipService.ToolTip="{Binding Description}" 
                        RenderTransformOrigin="0.5,1" Tapped="spotPin_Tapped">


                 <StackPanel Orientation="Horizontal" Tag="{Binding ID}">
                     <Grid>
                         <!-- Karratua -->
                         <Rectangle Width="25" Height="25" Fill="{StaticResource DarkGreyThemeColor}" Opacity="0.5"/>
                         <Rectangle Width="25" Height="25" Fill="{x:Null}" Stroke="Black" StrokeThickness="0.5" />
                         <!-- Borobila -->
                         <Image Source="{Binding MainTag}" Height="20" Width="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                      </Grid>

                      <StackPanel Background="{StaticResource DarkGrey75ThemeColor}">
                          <TextBlock Text="{Binding Title}" Margin="5,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="50" MaxLines="2" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" Style="{StaticResource BaseTextBlockStyle}" FontSize="11" Foreground="{StaticResource LightGreyThemeColor}" LineHeight="11"/>
                       </StackPanel>
                   </StackPanel>

                   <Rectangle Width="2" Height="10" Fill="Black" StrokeThickness="0" StrokeEndLineCap="Triangle" />

               </StackPanel>
           </DataTemplate>
       </Maps:MapItemsControl.ItemTemplate>
   </Maps:MapItemsControl>

这是 DataModel:

        private class SpotElement
    {
        public int ID { get; set; }
        public Visibility isVisible { get; set; }
        public bool isSelected { get; set; }

        public Visibility score1 { get; set; }
        public Visibility score2 { get; set; }
        public Visibility score3 { get; set; }
        public int Rating { get; set; }

        public string Title { get; set; }
        public string Description { get; set; }

        public double Distance { get; set; }

        public Geopoint geopoint { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
        public double Altitude { get; set; }

        public DateTime[] Date { get; set; }

        public globalVars.TagImageURL[] Tag { get; set; }
        public string MainTag { get; set; }

        public Point NormalizedAnchorPoint { get; set; }

        public string grouping { get; set; }
    }

    private ObservableCollection<SpotElement> allSpots;

我有一些与之相关的问题。

  1. 当我更改 ObservableCollection 时,例如 isVisible 值(通过过滤器中的选项显示或隐藏),项目根本没有改变。 这是过滤项目可见性的代码:

    /// <summary>
    /// Filtratu egiten ditu erakutsi beharreko spot-ak
    /// </summary>
    private void FilterSpots()
    {
        foreach (var item in allSpots)
        {
            // TODO: tag-ak falta dira filtratzeko
            bool visibilitySelected = true;
            if (Filter.showOnlySelected)
            {
                visibilitySelected = (item.isSelected == true);
            }
            bool visibilityBool = visibilitySelected && item.Rating >= Filter.minRating;
            Visibility visible = GlobalFunc.BoolToVisibility(visibilityBool);
    
            if (visible != item.isVisible)
            {
                item.isVisible = visible;
            }
    
            //Debug.WriteLine(item.Title + ": Rating {0} >= {1}? " + item.isVisible, item.Rating, Filter.minRating);
        }
        //mapSpotsItems.ItemsSource = null;
        //mapSpotsItems.ItemsSource = allSpots;
    }
    

    注释的调试行是我用来检查 ObservableCollection (allSpots) 上的值是否正确的行。 接下来的 2 行(mapSpotsItems.ItemsSource = null;和 mapSpotsItems.ItemsSource = allSpots;)是我要过滤项目的唯一一种模式。我认为这是最糟糕的做法,但尽管隐藏和再次显示需要时间(有时地图无法正常工作需要 20 秒),但在测试时它仍然有效。 在这里,我检查值是否为真则可见性是否可见,如果为假则折叠。

        /// <summary>
    /// Booleanetik Visibility-ra itzultzen du. True bada pasatako booleana, Visible izango da; Collapsed bestela.
    /// </summary>
    /// <param name="testBool"></param>
    /// <returns></returns>
    public static Visibility BoolToVisibility(bool testBool)
    {
        if (testBool) return Visibility.Visible;
        else return Visibility.Collapsed;
    }
    
  2. 创建项目(我有 2000-3000 个项目)非常慢,平移地图时移动有明显的滞后。有什么方法可以让它更愉快、反应更灵敏吗?

  3. 最后一个问题,尽管我设置了 RenderTransformOrigin="0.5,1",但好像我设置了 RenderTransformOrigin="0.0,0.0",从左上边界渲染。 。如果您查看图像,该项目是从红点渲染的,而不是应该渲染的蓝点。

谢谢!

When I change the ObservableCollection, like the isVisible value (to show or to hide by the choices in the filter, the items didn't change at all.

VisibilityEnum 但不是 bool。您需要为 xaml 创建 BoolToVisConverter

public class BoolToVisConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return (value is bool && (bool)value) ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return value is Visibility && (Visibility)value == Visibility.Visible; 
    }
}

The creation of the items (I have like 2000-3000 item) is very slow and when panning the map the move with a visible lag. Is it any way to make it more pleasant and responsive?

MapItemsControlListViewGridView不同,不支持UI virtualization。为了性能,请避免一次渲染太多项目

And the last question, despite I have set RenderTransformOrigin="0.5,1" it is as if I had set RenderTransformOrigin="0.0,0.0", rendered from the upper left boundary.

RenderTransformOrigin property is not used to set AnchorPoint. For setting right layout you could set NormalizedAnchorPoint.

<maps:MapItemsControl.ItemTemplate>
    <DataTemplate>
        <Button x:Name="mapItemButton" Click="mapItemButton_Click" Background="Transparent">
            <StackPanel>
                <Border Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
                    <TextBlock Text="{Binding DisplayName}"/>
                </Border>
                <Image Source="{Binding ImageSourceUri}"
                           maps:MapControl.NormalizedAnchorPoint="{Binding NormalizedAnchorPoint}"
                           maps:MapControl.Location="{Binding Location}">
                    <Image.Transitions>
                        <TransitionCollection>
                            <EntranceThemeTransition/>
                        </TransitionCollection>
                    </Image.Transitions>
                </Image>
            </StackPanel>
        </Button>
    </DataTemplate>
</maps:MapItemsControl.ItemTemplate>

更多细节请参考官方代码sample.