我是否正确创建了这个网格?
Am I creating this grid properly?
我正在尝试创建一个应用程序(目前)查看您的相机胶卷并在网格中显示您的图像。我设法让一个图像开始显示,但是当我尝试动态创建网格行时,没有图像显示。有人可以指出我可能做错了什么以及如何正确地做到这一点吗?我是 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();
}
}
首先,不要使用:
imageblock.SetValue(Grid.ColumnProperty, Count % 3);
而改用相当于
Grid.SetColumn(imageblock, Count % 3);
在我看来,第二个看起来更简单易用 :)
第二,动态添加新的行和列不是一个好主意:每次您 添加新行/列 从您的collection 中删除一个项目。
尝试使用 ListView,将源绑定到可观察的 collection 并在 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>
然后您必须创建一个 class 实现 INotyfy属性Changed,在您的页面构造函数中创建一个实例并将其分配给您的 DataContext。
在那个 class 里面,你会有这样的东西:
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 中的那个 属性 获取源 collection,并且由于源 属性 是一个 ObservableColleciton,每次您添加一个项目时,ListView 都会收到通知,它将更新其布局:)
图像不显示的原因是您没有将它们添加到网格中。设置图像后,将它们添加到 MainGrid 的子节点,您的代码应该可以工作
MainGrid.Children.Add(imageblock);
除此之外,您的代码还不错,尽管比必要的要复杂。正如 Sergio 建议的那样,您可以通过数据绑定大大简化这一过程。数据绑定可以让您将数据和表示分开:您可以在代码中保存一组图像并描述它们在 Xaml 中的显示方式。
如果您创建一个包含相机胶卷中的位图图像的 ObservableCollection,您可以根据需要添加到它,绑定将自动在 Xaml 中显示新图像(ObservableCollection 实现 INotifyCollectionChanged 添加或删除项目时报告的魔法)。您还可以绑定到具有不同外观的多个控件。如果您只需要图像,可以将它们直接添加到集合中。更常见的是,您还会将 class 与其他数据绑定,例如,您可能会包含图像及其名称。
在 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)
我正在尝试创建一个应用程序(目前)查看您的相机胶卷并在网格中显示您的图像。我设法让一个图像开始显示,但是当我尝试动态创建网格行时,没有图像显示。有人可以指出我可能做错了什么以及如何正确地做到这一点吗?我是 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();
}
}
首先,不要使用:
imageblock.SetValue(Grid.ColumnProperty, Count % 3);
而改用相当于
Grid.SetColumn(imageblock, Count % 3);
在我看来,第二个看起来更简单易用 :)
第二,动态添加新的行和列不是一个好主意:每次您 添加新行/列 从您的collection 中删除一个项目。
尝试使用 ListView,将源绑定到可观察的 collection 并在 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>
然后您必须创建一个 class 实现 INotyfy属性Changed,在您的页面构造函数中创建一个实例并将其分配给您的 DataContext。
在那个 class 里面,你会有这样的东西:
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 中的那个 属性 获取源 collection,并且由于源 属性 是一个 ObservableColleciton,每次您添加一个项目时,ListView 都会收到通知,它将更新其布局:)
图像不显示的原因是您没有将它们添加到网格中。设置图像后,将它们添加到 MainGrid 的子节点,您的代码应该可以工作
MainGrid.Children.Add(imageblock);
除此之外,您的代码还不错,尽管比必要的要复杂。正如 Sergio 建议的那样,您可以通过数据绑定大大简化这一过程。数据绑定可以让您将数据和表示分开:您可以在代码中保存一组图像并描述它们在 Xaml 中的显示方式。
如果您创建一个包含相机胶卷中的位图图像的 ObservableCollection,您可以根据需要添加到它,绑定将自动在 Xaml 中显示新图像(ObservableCollection 实现 INotifyCollectionChanged 添加或删除项目时报告的魔法)。您还可以绑定到具有不同外观的多个控件。如果您只需要图像,可以将它们直接添加到集合中。更常见的是,您还会将 class 与其他数据绑定,例如,您可能会包含图像及其名称。
在 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)