我正在尝试创建一个应用程序(现在)通过相机胶卷查看并在网格中显示图像。我设法最初显示一个图像,但是当我尝试动态创建网格行时,没有显示图像。有人可以指出我可能做错了什么以及如何正确地做到这一点?我是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();
}
}
答案 0 :(得分:1)
首先,不要使用:
imageblock.SetValue(Grid.ColumnProperty, Count % 3);
而使用相当于
Grid.SetColumn(imageblock, Count % 3);
并且在我看来第二个看起来更直接使用:)
第二件事,dinamically添加新的行和列不是一个好主意:每次添加新的时,你必须更新所有所有图像的列和行索引行/列从集合中删除项目。
尝试使用ListView,将源绑定到可观察的集合,并在ListView中使用Horizontal 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)