带有Itemtemplate或IValueConverter的LongListSelector的严重错误

时间:2014-10-08 20:50:52

标签: windows windows-phone-8 datatemplate itemtemplate longlistselector

我要脱掉头发,但在我这样做之前,我会尝试向你们寻求帮助......也许有人有同样的问题可以帮助我。

所以这是交易。我有一个名为SourceZoneSelect的LongListSelector定义如下:

<phone:LongListSelector x:Name="SourceZoneSelect" Grid.Row="2" 
                LayoutMode="Grid" 
                GridCellSize="160,160"
                BorderThickness="0"
                HorizontalContentAlignment="Stretch"
                VerticalContentAlignment="Stretch"
                Background="White"
                Width="480" Foreground="Black" 
                ItemTemplate="{StaticResource DataTemplateContentZone}"
                Style="{StaticResource LongListSelectorStyleContentZone}"
                ScrollViewer.VerticalScrollBarVisibility="Visible" Margin="-2,0,0,0"/>

ItemTemplate是一个DataTemplateSelector:

            <DataTemplate x:Key="DataTemplateContentZone">
                    <local:ContentZoneTemplateSelector Content="{Binding}" VerticalAlignment="Top" HorizontalAlignment="Right">
                        ...
                        <local:ContentZoneTemplateSelector.PhotoWebSelect>
                            <DataTemplate>
                                <Grid Height="158" Width="158">
                                    <Button BorderThickness="0" Style="{StaticResource ButtonStyleStyle}" Width="158" Height="158" toolkit:TiltEffect.IsTiltEnabled="True" Click="Button_SourceZone_Select_Click">
                                        <Grid HorizontalAlignment="Left" Height="158">
                                            <Rectangle Fill="{StaticResource StayfilmThirdColor}" HorizontalAlignment="Left" Height="158" Stroke="Black" VerticalAlignment="Top" Width="158"/>
                                            <Image x:Name="img" Stretch="UniformToFill" Width="158" Height="158" Source="{Binding Thumb}" Tag="{Binding ImgUrl}"/>
                                            <Grid x:Name="GridSelected" Tag="{Binding idMedia}" HorizontalAlignment="Right" Height="35" VerticalAlignment="Top" Width="35" Background="#FF0E9B00" Visibility="{Binding selected, Converter={StaticResource PhotoSelectedConverter}}">
                                                <Path Data="F1M0.555,6.585L0.089,6.077C-0.036,5.942,-0.029,5.73,0.107,5.605L1.464,4.344C1.525,4.287 1.606,4.255 1.689,4.255 1.785,4.255 1.871,4.293 1.935,4.361L5.661,8.373 12.07,0.126C12.134,0.047 12.23,0 12.334,0 12.41,0 12.481,0.024 12.54,0.07L14.003,1.206C14.073,1.26 14.117,1.339 14.128,1.429 14.141,1.518 14.116,1.606 14.061,1.674L5.826,12.263z" Fill="White" Margin="0" UseLayoutRounding="False" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                                            </Grid>
                                        </Grid>
                                    </Button>
                                </Grid>
                            </DataTemplate>
                        </local:ContentZoneTemplateSelector.PhotoWebSelect>
                        <local:ContentZoneTemplateSelector.VideoSelect>
                        <DataTemplate>
                            <Grid Height="158" Width="158">
                                <Button BorderThickness="0" Style="{StaticResource ButtonStyleStyle}" Width="Auto" Height="Auto" toolkit:TiltEffect.IsTiltEnabled="True" Click="Button_SourceZone_Select_Click">
                                    <Grid Height="158" Width="158">
                                        <Image x:Name="videoThumb" Stretch="Fill" Width="158" Height="158" Source="{Binding VideoThumbUrl}"/>
                                        <Image HorizontalAlignment="Center" Height="80" VerticalAlignment="Center" Width="80" Source="/Assets/Dark/feature.video.png"/>
                                        <Grid x:Name="GridSelected" Tag="{Binding idMedia}" HorizontalAlignment="Right" Height="35" VerticalAlignment="Top" Width="35" Background="#FF0E9B00" Visibility="{Binding Selected, Converter={StaticResource VideoSelectedConverter}}">
                                            <Path Data="F1M0.555,6.585L0.089,6.077C-0.036,5.942,-0.029,5.73,0.107,5.605L1.464,4.344C1.525,4.287 1.606,4.255 1.689,4.255 1.785,4.255 1.871,4.293 1.935,4.361L5.661,8.373 12.07,0.126C12.134,0.047 12.23,0 12.334,0 12.41,0 12.481,0.024 12.54,0.07L14.003,1.206C14.073,1.26 14.117,1.339 14.128,1.429 14.141,1.518 14.116,1.606 14.061,1.674L5.826,12.263z" Fill="White" Margin="0" UseLayoutRounding="False" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                                        </Grid>
                                    </Grid>
                                </Button>
                            </Grid>
                        </DataTemplate>
                    </local:ContentZoneTemplateSelector.VideoSelect>
...
</local:ContentZoneTemplateSelector>
        </DataTemplate>

还有2个值转换器:

in .xaml file

<phone:PhoneApplicationPage.Resources>
        <local:PhotoSelectedConverter x:Name="PhotoSelectedConverter"/>
        <local:VideoSelectedConverter x:Name="VideoSelectedConverter"/>


in .cs file

    public class PhotoSelectedConverter : IValueConverter
    {
        public object Convert(object value, Type typeName, object parameter, CultureInfo language)
        {
            bool selected = (bool)value;
            if (!selected)
            {
                return "Collapsed";
            }
            else
            {
                return "Visible";
            }
        }

        public object ConvertBack(object value, Type typeName, object parameter, CultureInfo language)
        {
            return DependencyProperty.UnsetValue;
        }
    }

    public class VideoSelectedConverter : IValueConverter
    {
        public object Convert(object value, Type typeName, object parameter, CultureInfo language)
        {
            double selected = (double)value;
            if (selected == 0.0)
            {
                return "Collapsed";
            }
            else
            {
                return "Visible";
            }
        }

        public object ConvertBack(object value, Type typeName, object parameter, CultureInfo language)
        {
            return DependencyProperty.UnsetValue;
        }
    }

这是直接管理名为GridSelected的Grid的代码,该Grid在datatemplate上定义,就好像绑定的项目 - &gt; selected属性为false,GridSelected应该是Collapsed,如果为true,那么它应该是Visible ......

这是代码:

            ...     List<StayClassLibrary.Media> medias = await Media.GetMediasByAlbum(albmLst, App.Current.AppUser, App.Current.WSConfig);

                    if (selectedSourceZone.Count > 0)
                    {
                        selectedSourceZone.Clear();
                    }
                    selectedSourceZone = null;
                    selectedSourceZone = new ObservableCollection<IDisposable>();

                    SourceZoneSelect.ClearValue(LongListSelector.DataContextProperty);
                    SourceZoneSelect.ClearValue(LongListSelector.ItemsSourceProperty);

                    SourceZoneSelect.UpdateLayout();
                    popupSourceZone_Select.UpdateLayout();
                    GridSourceZoneSelect.UpdateLayout();

                    if (medias.Count == 0)
                    {
                        NoImagesFound.Visibility = System.Windows.Visibility.Visible;
                    }
                    else
                    {
                        NoImagesFound.Visibility = System.Windows.Visibility.Collapsed;

                        //TODO criar PictureItems
                        foreach (StayClassLibrary.Media item in medias)
                        {
                            BitmapImage b = new BitmapImage();
                            b.UriSource = new Uri(item.thumbnail, UriKind.RelativeOrAbsolute);
                            b.ImageFailed += b_ImageFailed;

                            bool found = false;
                            foreach (var media in selectedContentZone)
                            {
                                if(media.GetType() == typeof(PictureItemWeb))
                                {
                                    if(((PictureItemWeb)media).idMedia == item.idMidia)
                                    {
                                        if (!selectedSourceMedias.Contains(item.idMidia.ToString()))
                                        {
                                            found = true;
                                        }
                                        break;
                                    }
                                }
                                else if(media.GetType() == typeof(VideoItem))
                                {
                                    if (((VideoItem)media).idMedia == item.idMidia)
                                    {
                                        if (!selectedSourceMedias.Contains(item.idMidia.ToString()))
                                        {
                                            found = true;
                                        }
                                        break;
                                    }
                                }
                            }

                            if (item.type == "image")
                            {
                                selectedSourceZone.Insert(0, new PictureItemWeb
                                {
                                    Thumb = b,
                                    Pic = new BitmapImage(new Uri(item.source, UriKind.RelativeOrAbsolute)),
                                    dateBinary = DateTime.Now.ToBinary(),
                                    idAlbum = item.idAlbum,
                                    idMedia = item.idMidia,
                                    ImgUrl = item.source,
                                    ThumbUrl = item.thumbnail,
                                    selected = false,
                                    selectable = true,
                                    added = found,
                                    cancellationToken = new CancellationTokenSource()
                                });
                            }
                            else if (item.type == "video")
                            {
                                selectedSourceZone.Insert(0, new VideoItem
                                {
                                    Thumb = b,
                                    dateBinary = DateTime.Now.ToBinary(),
                                    idAlbum = item.idAlbum,
                                    idMedia = item.idMidia,
                                    VideoUrl = item.source,
                                    VideoThumbUrl = item.thumbnail,
                                    Selected = 0.0,
                                    selectable = true,
                                    added = found,
                                    cancellationToken = new CancellationTokenSource()
                                });
                            }
                            b = null;
                        }

                        if (selectedSourceZone.Count > 0)
                        {
                            Storyboard sb = new Storyboard();
                            DoubleAnimation fadein = new DoubleAnimation();
                            fadein.From = 0.0;
                            fadein.To = 1.0;
                            fadein.Duration = new Duration(TimeSpan.FromSeconds(0.35));
                            Storyboard.SetTarget(fadein, SourceZoneSelect);
                            Storyboard.SetTargetProperty(fadein, new PropertyPath("Opacity"));
                            sb.Children.Add(fadein);
                            sb.Begin();

                            SourceZoneSelect.ItemsSource = null;
                            SourceZoneSelect.ClearValue(LongListSelector.DataContextProperty);
                            SourceZoneSelect.ClearValue(LongListSelector.ItemsSourceProperty);
                            SourceZoneSelect.ItemsSource = selectedSourceZone;
// *1 

                            foreach (var item in selectedSourceZone)
                            {
                                if(item.GetType() == typeof(PictureItemWeb))
                                {
                                    if(selectedSourceMedias.Contains(((PictureItemWeb)item).idMedia.ToString()))
                                    {
                                        ((PictureItemWeb)item).selected = true;
                                    }
                                }
                                else if (item.GetType() == typeof(VideoItem))
                                {
                                    if (selectedSourceMedias.Contains(((VideoItem)item).idMedia.ToString()))
                                    {
                                        ((VideoItem)item).Selected = 1.0;
                                    }
                                }
                                UpdateSelectedState(SourceZoneSelect, item);    // *2
                            }
                        }
                        else
                        {
                            NoImagesFound.Visibility = System.Windows.Visibility.Visible;
                            Storyboard sb = new Storyboard();
                            DoubleAnimation fadein = new DoubleAnimation();
                            fadein.From = 0.0;
                            fadein.To = 1.0;
                            fadein.Duration = new Duration(TimeSpan.FromSeconds(0.35));
                            Storyboard.SetTarget(fadein, NoImagesFound);
                            Storyboard.SetTargetProperty(fadein, new PropertyPath("Opacity"));
                            sb.Children.Add(fadein);
                            sb.Begin();
                        }
                    }
当我设置SourceZoneSelect.ItemsSource = selectedSourceZone时,

* 1它应该激活IValueConverter并且它没有...我在那里有一个断点,它永远不会通过那里。

* 2此函数UpdateSelectedState()我创建了尝试手动修复和更新每个媒体的GridSelected可见性

private void UpdateSelectedState(DependencyObject targetElement, object item)
    {
        var count = VisualTreeHelper.GetChildrenCount(targetElement);
        if (count == 0)
            return;

        for (int i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(targetElement, i);
            if (child is Button)
            {
                Button targetItem = (Button)child;

                if (item.GetType() == typeof(PictureItemWeb))
                {
                    if (((PictureItemWeb)targetItem.DataContext).idMedia == ((PictureItemWeb)item).idMedia)
                    {
                        var g = targetItem.FindName("GridSelected");
                        if (((Guid)((Grid)g).Tag) == ((PictureItemWeb)item).idMedia)
                        {
                            if (((PictureItemWeb)item).selected)
                            {
                                ((Grid)g).Visibility = System.Windows.Visibility.Visible;
                            }
                            else
                            {
                                ((Grid)g).Visibility = System.Windows.Visibility.Collapsed;
                            }
                        }
                        return;
                    }
                }
                else if (item.GetType() == typeof(VideoItem))
                {
                    if (((VideoItem)targetItem.DataContext).idMedia == ((VideoItem)item).idMedia)
                    {
                        var g = targetItem.FindName("GridSelected");
                        if (((VideoItem)item).Selected == 1.0)
                        {
                            ((Grid)g).Visibility = System.Windows.Visibility.Visible;
                        }
                        else
                        {
                            ((Grid)g).Visibility = System.Windows.Visibility.Collapsed;
                        }
                        return;
                    }
                    return;
                }
            }
            else
            {
                UpdateSelectedState(child, item);
            }
        }
    }

这是我点击图片时的代码。 (它所做的只是将selected属性更改为true / false并显示/隐藏单击项目的GridSelected:

private void Button_SourceZone_Select_Click(object sender, RoutedEventArgs e)
    {
        var media = ((Button)sender).DataContext;
        if (media.GetType() == typeof(PictureItemWeb))
        {
            int index = selectedSourceZone.IndexOf(((PictureItemWeb)((Button)sender).DataContext));
            if (index != -1)
            {
                ((PictureItemWeb)selectedSourceZone.ElementAt(index)).selected = !((PictureItemWeb)selectedSourceZone.ElementAt(index)).selected;
            }

            var g = ((Button)sender).FindName("GridSelected");

            if (((PictureItemWeb)selectedSourceZone.ElementAt(index)).selected)
            {
                ((Grid)g).Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                ((Grid)g).Visibility = System.Windows.Visibility.Collapsed;
            }
        }
        else if (media.GetType() == typeof(VideoItem))
        {
            int index = selectedSourceZone.IndexOf(((VideoItem)((Button)sender).DataContext));
            if (index != -1)
            {
                ((VideoItem)selectedSourceZone.ElementAt(index)).Selected = (((VideoItem)selectedSourceZone.ElementAt(index)).Selected == 0.0) ? 1.0 : 0.0;
            }

            var g = ((Button)sender).FindName("GridSelected");

            if (((VideoItem)selectedSourceZone.ElementAt(index)).Selected == 1.0)
            {
                ((Grid)g).Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                ((Grid)g).Visibility = System.Windows.Visibility.Collapsed;
            }
        }
    }

好的所有代码现在都在这里。

我唯一没有发布的是当我点击确认选择时的功能..它所做的就是将媒体的ID添加到列表中,如:

selectedSourceMedias.Add(((PictureItemWeb)item).idMedia.ToString());

然后关闭弹出窗口并将longlistselector设置为null。

所以当我点击按钮再次显示列表时。它重新创建了整个列表!如我发布的第一个代码所示(它请求媒体,再次将longlistselector设置为null并重新创建longlist Items(PictureWeb和VideoItem都是IDisposable)。

最后!这让我很生气。我已经调试过,并且它应该完美无缺!但情况如下:

  1. 我第一次打开,所有媒体都未被选中。非常好。 (该 ValueConverter首次在这里激活)
  2. 然后,如果我关闭并再次打开,他们会重新创建,但仍然都是 未选中(GridSelected都是折叠的)(但现在是 ValueConverter未激活)
  3. 现在我选择了前3个媒体,我点击的3个UI元素的GridSelected被更改为 可见,然后我确认选择。 (我调试了正确的 ID已保存在selectedSourceMedias)
  4. 然后我点击再次打开列表。 (一切都会在之前再次创建 // * 1我将ItemsSource设置为新创建的selectedSourceZone,并且不调用ValueConverted)
  5. 在// * 1之后我手动将所选的和UpdateSelectedStatus()设置为每个(这也是在调试时选择的正确媒体(从第一个到第三个)通过该行 ((网格)g).Visibility = System.Windows.Visibility.Visible; 并且在selectedSourceMedias ID列表中没有的所有其他内容都会通过Collapsed行...
  6. 现在当所有代码运行并且它返回到模拟器时,顶部的3张照片(应该看到GridSelected可见的照片是折叠的,并且列表末尾的3张照片显示为选中!! !(这是让我疯狂的错误)
  7. 还有更多!!!如果我点击另一个加载完全新媒体的按钮(ValueConverted被激活并且全部通过Collapsed(这是好的)),它会显示模拟器,前三张照片显示为选中!!!
  8. 所以我觉得某个地方有一个内部错误,可以保存具有相同名称的数据模板(&#34; GridSelected&#34;)

    我知道这可能会让你有点头疼但是......请尽量帮助我!

    如果您遇到类似问题以及如何解决问题,请告诉我。

    提前谢谢大家!!!

1 个答案:

答案 0 :(得分:1)

我找到了问题的解决方案......如果你们中的任何一个发现自己遇到了这个问题......请注意框架中的某个地方有一个没有清除缓存或其他内容的错误。解决方案是我在设置SourceZoneSelect.ItemsSource之前添加这些行:

SourceZoneSelect.ClearValue(LongListSelector.ItemTemplateProperty);
SourceZoneSelect.ItemTemplate = null;
SourceZoneSelect.ItemTemplate = this.Resources["DataTemplateContentZone"] as DataTemplate;

因此,如果您想每次都运行转换器,则需要手动清除模板并再次应用