我正确地创建了这个网格吗?

时间:2015-02-04 19:57:27

标签: c# windows-phone-8.1

我正在尝试创建一个应用程序(现在)通过相机胶卷查看并在网格中显示图像。我设法最初显示一个图像,但是当我尝试动态创建网格行时,没有显示图像。有人可以指出我可能做错了什么以及如何正确地做到这一点?我是C#编程和Windows Phone开发的新手,所以我为业余问题道歉。

public async void PrintInformation()
    {
        try
        {
            TextBlock.Text = "";
            IReadOnlyCollection<StorageFile> PicLib = await KnownFolders.CameraRoll.GetFilesAsync();
            IEnumerator<StorageFile> PicLibEnum = PicLib.GetEnumerator();
            Debug.WriteLine(PicLib.Count);
            int Count = 0;
            foreach (StorageFile Pic in PicLib)
            {
                if (Count % 3 == 0)
                {
                    Debug.WriteLine("Creating new row..." + Count % 3);
                    MainGrid.RowDefinitions.Add(new RowDefinition());
                }
                Image imageblock = new Image();
                imageblock.SetValue(Grid.ColumnProperty, Count % 3);
                imageblock.SetValue(Grid.RowProperty, Count / 3);
                Debug.WriteLine(imageblock);
                TextBlock.Text += Pic.Path + "\n";
                IRandomAccessStream PicStream = await Pic.OpenReadAsync();
                BitmapImage Bmp = new BitmapImage();
                await Bmp.SetSourceAsync(PicStream);
                //Uri Uri = new Uri(Pic.Path, UriKind.Absolute);
                //Bmp.UriSource = Uri;
                imageblock.Source = Bmp;
                //break;
                Count++;
            }
        }
        catch (Exception e)
        {
            TextBlock.Text = e.ToString();
        }
    }

2 个答案:

答案 0 :(得分:1)

首先,不要使用:

imageblock.SetValue(Grid.ColumnProperty, Count % 3);

而使用相当于

Grid.SetColumn(imageblock, Count % 3);

并且在我看来第二个看起来更直接使用:)

第二件事,dinamically添加新的行和列不是一个好主意:每次添加新的时,你必须更新所有所有图像的列和行索引行/列从集合中删除项目。 尝试使用ListView,将源绑定到可观察的集合,并在ListView中使用Horizo​​ntal WrapGrid。 然后只需使用图像创建自己的DataTemplate,将其源代码绑定到ObservableCollection的每个元素,然后就可以了:)

您将能够添加新图像而无需担心布局和网格索引。

编辑:这是XAML中的一般想法

<ListView ItemsSource="{Binding Source}"
          ItemTemplate="{StaticResource ImageTemplate}"                  
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapGrid Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

或者正如Rob Caplan所说,你可以使用GridView,最终结果几乎相同。

然后在你的Page.Resources部分,例如:

<DataTemplate x:Key="ImageTemplate">
    <Grid Margin="5,5,5,0" Height="45" Width="45">
        <Image Source="{Binding}"/>
    </Grid>
</DataTemplate>

然后你必须创建一个实现INotyfyPropertyChanged的类,在你的页面构造函数中创建一个实例并将它分配给你的DataContext。

在该课程中,您将拥有以下内容:

private ObservableCollection<ImageSource> _Source = new ObservableCollection<ImageSource>();

public ObservableCollection<ImageSource> Source
{
    get
    {
        return this._Source;
    }
    set
    {
        if (this._Source != value)
        {
            this._Source = value;
            this.OnPropertyChanged();
        }
    }
}

现在,ListView将从ViewModel中的该属性获取源集合,并且由于Source属性是ObservableColleciton,因此每次添加项目时,ListView都会收到通知,并且会更新其布局:)

答案 1 :(得分:1)

图像未显示的原因是您不将它们添加到网格中。设置完图像后,将它们添加到MainGrid的子项中,您的代码应该可以正常工作

MainGrid.Children.Add(imageblock);

其他的是你的代码很好,虽然比必要的复杂。正如塞尔吉奥建议你可以通过数据绑定大大简化这一点。数据绑定将使您可以将数据和表示分开:您可以在代码中保留图像集合,并描述它们在Xaml中的显示方式。

如果您从相机胶卷创建包含BitmapImages的ObservableCollection,则可以根据需要添加它,并且绑定将自动在Xaml中显示新图像(ObservableCollection实现INotifyCollectionChanged魔术以报告项目时间被添加或删除)。您还可以绑定到具有不同外观的多个控件。如果您只想要图像,可以直接将它们添加到集合中。更常见的是,您也将绑定到包含其他数据的类,例如,您可能包含图像及其名称。

在Xaml中,您将使用ItemsControl来显示集合。由于你想要一个网格,GridView是一个不错的选择。如果你想要一个列表,每个项目都在自己的行中,那么ListView会更好。您可以设置ItemTemplate来控制图像的显示方式:

<GridView ItemsSource="{Binding}">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Image Source="{Binding Image}" />
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>            
</GridView>

有关详细信息,请参阅MSDN上的Data binding overview (XAML)