ImageGallery 不会从其他 class 更新
ImageGallery won't update from other class
所以我试图从服务器以字节为单位下载图像,但图像不显示。我得到一个正确的字节数组并重新调整它。它可以从 imagegallerypagemodel 添加图片,但从 IssuePageModel 添加它们时不起作用。所以我怀疑 class 被错误地实例化或者 notifyproperty 不起作用。我试图只添加相关部分,但可以添加任何遗漏的内容。
合集
public class ImageGalleryPageModel
{
public ObservableCollection<ImageModel> Images
{
get { return images; }
}
private ObservableCollection<ImageModel> images = new ObservableCollection<ImageModel>();
这可以添加来自此 class
的图片
private async Task ExecutePickCommand()
{
MediaFile file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
byte[] imageAsBytes;
using (MemoryStream memoryStream = new MemoryStream())
{
file.GetStream().CopyTo(memoryStream);
file.Dispose();
imageAsBytes = memoryStream.ToArray();
}
if (imageAsBytes.Length > 0)
{
IImageResizer resizer = DependencyService.Get<IImageResizer>();
imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080);
ImageSource imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
Images.Add(new ImageModel { Source = imageSource, OrgImage = imageAsBytes });
}
}
然后我第二次加载 issuepagemodel,这里是 imagegallerypagemodel 的实例
public class IssuePageModel : FreshBasePageModel, INotifyPropertyChanged
{
public ImageGalleryPageModel ImageGalleryViewModel { get; set; } = new ImageGalleryPageModel();
然后我把图片下载下来放到Collection里面,notify属性被触发了,debug的时候可以看到get上了,但是set的部分看不到。
private void AddTheImages(int imageIssueId)
{
var imageData = App.Client.GetImage(imageIssueId);
byte[] imageAsBytes = imageData.Item1;
if (imageAsBytes.Length > 0)
{
IImageResizer resizer = DependencyService.Get<IImageResizer>();
imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080);
ImageSource imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
ImageGalleryViewModel.Images.Add(new ImageModel { Source = imageSource, OrgImage = imageAsBytes });
}
}
整个Xaml
<freshMvvm:FreshBaseContentPage NavigationPage.HasNavigationBar="false" xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:freshMvvm="clr-namespace:FreshMvvm;assembly=FreshMvvm"
xmlns:converters="clr-namespace:ASFT.Converters;assembly=ASFT"
xmlns:maps="clr-namespace:ASFT.PageModels;assembly=ASFT"
xmlns:controls="clr-namespace:ASFT.Controls;assembly=ASFT"
x:Class="ASFT.Pages.IssuePage" Padding="4,25,4,4" x:Name="IssuePages">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="Labelfont" TargetType="Label">
<Setter Property="FontSize" Value="Medium" />
</Style>
<converters:DateTextConverter x:Key="DateToTextConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<Grid BackgroundColor="Black">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<!--Top Navigation Bar RETURN TO EVENTS-->
<Grid Grid.Row="0" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Label Text=" < EVENTS" TextColor="White" FontSize="Large" HorizontalOptions="StartAndExpand"
VerticalOptions="CenterAndExpand">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnGoToListCommand}" NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
<Label Text="{Binding LocationText}" TextColor="Black"/>
</StackLayout>
</Grid>
<ScrollView Grid.Column="0" Grid.Row="1" Orientation="Vertical" VerticalOptions="FillAndExpand">
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Spacing="15" Padding="0,30,0,0">
<!--Category-->
<Label Text="CATEGORY" HorizontalTextAlignment="Start" VerticalTextAlignment="Center"
Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" Padding="2" HeightRequest="40">
<StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="FillAndExpand"
Spacing="6" HeightRequest="40">
<Entry Text="{Binding TitleEx}" TextColor="White" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Style="{StaticResource Labelfont}" HeightRequest="40"
BackgroundColor="Black" />
</StackLayout>
</Frame>
<!--Title-->
<Label Text="TITLE" HorizontalTextAlignment="Start" VerticalTextAlignment="Center"
Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" Padding="2" HeightRequest="40">
<StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="FillAndExpand"
Spacing="6" HeightRequest="40">
<Entry Text="{Binding TitleEx}" TextColor="White" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Style="{StaticResource Labelfont}" HeightRequest="40"
BackgroundColor="Black" />
</StackLayout>
</Frame>
<!--PictureGallery-->
<Label Text="IMAGES" HorizontalTextAlignment="Start" VerticalTextAlignment="Center"
Style="{StaticResource Labelfont}" TextColor="White" />
<Grid BindingContext="{Binding ImageGalleryViewModel}">
<Grid.RowDefinitions>
<RowDefinition Height="128" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<controls:ImageGalleryControl Grid.Row="0" ItemsSource="{Binding Images}">
<controls:ImageGalleryControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Source}" Aspect="AspectFit">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Path=BindingContext.PreviewImageCommand, Source={x:Reference IssuePages}}"
CommandParameter="{Binding ImageId}" />
</Image.GestureRecognizers>
</Image>
</DataTemplate>
</controls:ImageGalleryControl.ItemTemplate>
</controls:ImageGalleryControl>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Text="Add photo" Command="{Binding CameraCommand}" />
<Button Grid.Column="1" Text="Pick photo" Command="{Binding PickCommand}" />
</Grid>
</Grid>
<Label Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="3" Text="{Binding ImageText}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White" />
<!--Description-->
<Label Text="DESCRIPTION" HorizontalTextAlignment="Start" VerticalTextAlignment="Center" Style="{StaticResource Labelfont}" TextColor="White" />
<Frame Padding="2" OutlineColor="#FBB040">
<Editor Text="{Binding DescriptionEx}" HeightRequest="100" BackgroundColor="Black" TextColor="White" />
</Frame>
<!--Grid for Status and Severity-->
<Grid HorizontalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!--Severity-->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Text="SEVERITY" HorizontalTextAlignment="Start" VerticalTextAlignment="Center" Style="{StaticResource Labelfont}" TextColor="White" />
<Label Grid.Row="0" Grid.Column="1" Text="" VerticalTextAlignment="Center"
HorizontalOptions="StartAndExpand" Style="{StaticResource Labelfont}" />
<StackLayout Grid.Row="1" Grid.Column="0" Orientation="Horizontal" HorizontalOptions="Center">
<Image Source="severity_5.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity5Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_5.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="1">
<Image Source="severity_4.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity4Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_4.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="2">
<Image Source="severity_3.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity3Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_3.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="3">
<Image Source="severity_2.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity2Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_2.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="4">
<Image Source="severity_1.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity1Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_1.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<!--Status-->
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Text="STATUS" HorizontalTextAlignment="Start" VerticalTextAlignment="Center" TextColor="White" Style="{StaticResource Labelfont}" />
<Label Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" FontSize="Micro" Text="STATUS" HorizontalTextAlignment="End" VerticalTextAlignment="Center" TextColor="White"
Style="{StaticResource Labelfont}" IsVisible="True" />
<StackLayout Grid.Row="3" Grid.Column="1" Orientation="Horizontal" Spacing="0">
<Image Source="statusUnresolved.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding StatusUnresolvedOpacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="statusUnresolved.png"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="3" Grid.Column="2" Orientation="Horizontal" Spacing="4">
<Image Source="statusInProgress.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="{Binding StatusInProgressOpacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="statusInProgress.png"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="3" Grid.Column="3" Orientation="Horizontal" Spacing="4">
<Image Source="statusDone.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="{Binding StatusDoneOpacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="statusDone.png"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</Grid>
<!--Date Created-->
<Label Text="TIME AND DATE: " Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" BackgroundColor="Black" Padding="2">
<StackLayout Orientation="Horizontal" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Spacing="0" Margin="0" Padding="0"
BackgroundColor="Black" HeightRequest="40">
<Label Text=" " Style="{StaticResource Labelfont}" TextColor="White" BackgroundColor="Black"
Margin="1" />
<Label Text="{Binding CreatedEx, Converter={StaticResource DateToTextConverter}}"
Style="{StaticResource Labelfont}" TextColor="White" BackgroundColor="Black"
VerticalOptions="Center" />
</StackLayout>
</Frame>
<!--REPORTED BY-->
<Label Text="REPORTED BY: " Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" BackgroundColor="Black" Padding="2">
<StackLayout Orientation="Horizontal" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Spacing="0" Padding="1" BackgroundColor="Black"
HeightRequest="40">
<Label Text=" " Style="{StaticResource Labelfont}" TextColor="White" BackgroundColor="Black" />
<Label Text="{Binding CreatedByEx}" Style="{StaticResource Labelfont}"
TextColor="White" BackgroundColor="Black" VerticalOptions="Center" />
</StackLayout>
</Frame>
<!--Map View-->
<Grid>
<Grid.BindingContext>
<maps:TkMapPageModel/>
</Grid.BindingContext>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
<RowDefinition Height="40" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Label Grid.Column="1" Grid.Row="0" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"
Text="Tap and hold on map to set/move pin" Font="Large" />
<StackLayout Grid.Column="1" Grid.Row="1" VerticalOptions="FillAndExpand">
<RelativeLayout x:Name="MapRelativeLayout" VerticalOptions="FillAndExpand" HeightRequest="920" WidthRequest="300" />
</StackLayout>
<StackLayout Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="3" Orientation="Vertical" Spacing="0">
<Label Text="{Binding MapText}" VerticalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White" />
</StackLayout>
</Grid>
<Button Text="Submit"
HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand" Command="{Binding SubmitCommand}"
BackgroundColor="#FBB040" />
</StackLayout>
</ScrollView>
<!--Bottom Navigation Bar-->
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<StackLayout Grid.ColumnSpan="3" Grid.Row="1" Orientation="Horizontal"
HorizontalOptions="FillAndExpand" Spacing="5" BackgroundColor="White">
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Image Source="photo2.png" WidthRequest="100" HeightRequest="100" HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
</Image>
</StackLayout>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Image Source="photo2.png" WidthRequest="100" HeightRequest="100" HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
</Image>
</StackLayout>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Image Source="showmap.png" WidthRequest="100" HeightRequest="60" HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand">
</Image>
</StackLayout>
</StackLayout>
</Grid>
</Grid>
正如我重复的那样,它在从 imagegallerypagemodel 添加而不是从其他 class IssuePageModel
添加时有效
public class ImageGalleryControl : ScrollView
{
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create<ImageGalleryControl, IList>(
view => view.ItemsSource,
default(IList),
BindingMode.TwoWay,
propertyChanging: (bindableObject, oldValue, newValue) => {
((ImageGalleryControl)bindableObject).ItemsSourceChanging();
},
propertyChanged: (bindableObject, oldValue, newValue) => {
((ImageGalleryControl)bindableObject).ItemsSourceChanged(bindableObject, oldValue, newValue);
}
);
public IList ItemsSource
{
get
{
return (IList)GetValue(ItemsSourceProperty);
}
set
{
SetValue(ItemsSourceProperty, value);
}
}
Images
在你的模型中是一个 ObservableCollection
,它很像一个列表。当您添加图像时,您不会点击 set
因为您没有更改集合,而是添加到现有集合中。这是正确的方法... ObservableCollection
包含 INotifyCollectionChanged
接口,这意味着有一个 CollectionChanged
事件你可以订阅并监听变化。在任何项目源中使用 XAML 绑定时,它应该会自动为您侦听和处理此事件,但在后面的代码中或您自己代码中的任何地方,您很可能需要这样做。
请记住,集合引用也可能发生变化,因此您也需要对其进行处理。下面是如何正确处理模型之间 ObservableCollection
的示例。
public class ExampleModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<string> names = new ObservableCollection<string>();
public ObservableCollection<string> Names
{
get => names;
set
{
names = value;
//Only called if I change the collection reference i.e. make a new ObservableCollection or assign it to another exising reference.
//Not called adding or removing items from existing collection.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Names)));
}
}
}
.....
public class ExampleViewModel : INotifyPropertyChanged
{
private readonly ExampleModel ExampleModel;
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<string> names = new ObservableCollection<string>();
public ExampleViewModel()
{
ExampleModel = new ExampleModel();
ExampleModel.PropertyChanged += ExampleModel_PropertyChanged;
Names = ExampleModel.Names;
if (Names != null) Names.CollectionChanged += Names_CollectionChanged;
}
private void ExampleModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(ExampleModel.Names):
//Here we reassign the entire collection if it changes.
if (Names != null) Names.CollectionChanged -= Names_CollectionChanged;
Names = ExampleModel.Names;
if (Names != null) Names.CollectionChanged += Names_CollectionChanged;
break;
}
}
private void Names_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (var item in e.OldItems) Names.Remove((string)item);
foreach (var item in e.NewItems) Names.Add((string)item);
}
public ObservableCollection<string> Names
{
get => names;
set
{
names = value;
//Only called if I change the collection reference i.e. make a new ObservableCollection or assign it to another exising reference.
//Not called adding or removing items from existing collection.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Names)));
}
}
}
注意:这个例子只是为了让你更清楚地了解它是如何工作的,可能不是实现这两者的最简洁的方法。如果知道它们都是 ObservableCollections 那么那很好,但至少我们应该假设它们是 IEnumerable 并且处理方式略有不同。无论哪种方式......但是你需要在你的代码中手动处理它并且 XAML 应该在绑定到 ItemsSource 时为你处理它。
所以我试图从服务器以字节为单位下载图像,但图像不显示。我得到一个正确的字节数组并重新调整它。它可以从 imagegallerypagemodel 添加图片,但从 IssuePageModel 添加它们时不起作用。所以我怀疑 class 被错误地实例化或者 notifyproperty 不起作用。我试图只添加相关部分,但可以添加任何遗漏的内容。
合集
public class ImageGalleryPageModel
{
public ObservableCollection<ImageModel> Images
{
get { return images; }
}
private ObservableCollection<ImageModel> images = new ObservableCollection<ImageModel>();
这可以添加来自此 class
的图片 private async Task ExecutePickCommand()
{
MediaFile file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
byte[] imageAsBytes;
using (MemoryStream memoryStream = new MemoryStream())
{
file.GetStream().CopyTo(memoryStream);
file.Dispose();
imageAsBytes = memoryStream.ToArray();
}
if (imageAsBytes.Length > 0)
{
IImageResizer resizer = DependencyService.Get<IImageResizer>();
imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080);
ImageSource imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
Images.Add(new ImageModel { Source = imageSource, OrgImage = imageAsBytes });
}
}
然后我第二次加载 issuepagemodel,这里是 imagegallerypagemodel 的实例
public class IssuePageModel : FreshBasePageModel, INotifyPropertyChanged
{
public ImageGalleryPageModel ImageGalleryViewModel { get; set; } = new ImageGalleryPageModel();
然后我把图片下载下来放到Collection里面,notify属性被触发了,debug的时候可以看到get上了,但是set的部分看不到。
private void AddTheImages(int imageIssueId)
{
var imageData = App.Client.GetImage(imageIssueId);
byte[] imageAsBytes = imageData.Item1;
if (imageAsBytes.Length > 0)
{
IImageResizer resizer = DependencyService.Get<IImageResizer>();
imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080);
ImageSource imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
ImageGalleryViewModel.Images.Add(new ImageModel { Source = imageSource, OrgImage = imageAsBytes });
}
}
整个Xaml
<freshMvvm:FreshBaseContentPage NavigationPage.HasNavigationBar="false" xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:freshMvvm="clr-namespace:FreshMvvm;assembly=FreshMvvm"
xmlns:converters="clr-namespace:ASFT.Converters;assembly=ASFT"
xmlns:maps="clr-namespace:ASFT.PageModels;assembly=ASFT"
xmlns:controls="clr-namespace:ASFT.Controls;assembly=ASFT"
x:Class="ASFT.Pages.IssuePage" Padding="4,25,4,4" x:Name="IssuePages">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="Labelfont" TargetType="Label">
<Setter Property="FontSize" Value="Medium" />
</Style>
<converters:DateTextConverter x:Key="DateToTextConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<Grid BackgroundColor="Black">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<!--Top Navigation Bar RETURN TO EVENTS-->
<Grid Grid.Row="0" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Label Text=" < EVENTS" TextColor="White" FontSize="Large" HorizontalOptions="StartAndExpand"
VerticalOptions="CenterAndExpand">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnGoToListCommand}" NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
<Label Text="{Binding LocationText}" TextColor="Black"/>
</StackLayout>
</Grid>
<ScrollView Grid.Column="0" Grid.Row="1" Orientation="Vertical" VerticalOptions="FillAndExpand">
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Spacing="15" Padding="0,30,0,0">
<!--Category-->
<Label Text="CATEGORY" HorizontalTextAlignment="Start" VerticalTextAlignment="Center"
Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" Padding="2" HeightRequest="40">
<StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="FillAndExpand"
Spacing="6" HeightRequest="40">
<Entry Text="{Binding TitleEx}" TextColor="White" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Style="{StaticResource Labelfont}" HeightRequest="40"
BackgroundColor="Black" />
</StackLayout>
</Frame>
<!--Title-->
<Label Text="TITLE" HorizontalTextAlignment="Start" VerticalTextAlignment="Center"
Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" Padding="2" HeightRequest="40">
<StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="FillAndExpand"
Spacing="6" HeightRequest="40">
<Entry Text="{Binding TitleEx}" TextColor="White" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Style="{StaticResource Labelfont}" HeightRequest="40"
BackgroundColor="Black" />
</StackLayout>
</Frame>
<!--PictureGallery-->
<Label Text="IMAGES" HorizontalTextAlignment="Start" VerticalTextAlignment="Center"
Style="{StaticResource Labelfont}" TextColor="White" />
<Grid BindingContext="{Binding ImageGalleryViewModel}">
<Grid.RowDefinitions>
<RowDefinition Height="128" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<controls:ImageGalleryControl Grid.Row="0" ItemsSource="{Binding Images}">
<controls:ImageGalleryControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Source}" Aspect="AspectFit">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Path=BindingContext.PreviewImageCommand, Source={x:Reference IssuePages}}"
CommandParameter="{Binding ImageId}" />
</Image.GestureRecognizers>
</Image>
</DataTemplate>
</controls:ImageGalleryControl.ItemTemplate>
</controls:ImageGalleryControl>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Text="Add photo" Command="{Binding CameraCommand}" />
<Button Grid.Column="1" Text="Pick photo" Command="{Binding PickCommand}" />
</Grid>
</Grid>
<Label Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="3" Text="{Binding ImageText}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White" />
<!--Description-->
<Label Text="DESCRIPTION" HorizontalTextAlignment="Start" VerticalTextAlignment="Center" Style="{StaticResource Labelfont}" TextColor="White" />
<Frame Padding="2" OutlineColor="#FBB040">
<Editor Text="{Binding DescriptionEx}" HeightRequest="100" BackgroundColor="Black" TextColor="White" />
</Frame>
<!--Grid for Status and Severity-->
<Grid HorizontalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!--Severity-->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Text="SEVERITY" HorizontalTextAlignment="Start" VerticalTextAlignment="Center" Style="{StaticResource Labelfont}" TextColor="White" />
<Label Grid.Row="0" Grid.Column="1" Text="" VerticalTextAlignment="Center"
HorizontalOptions="StartAndExpand" Style="{StaticResource Labelfont}" />
<StackLayout Grid.Row="1" Grid.Column="0" Orientation="Horizontal" HorizontalOptions="Center">
<Image Source="severity_5.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity5Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_5.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="1">
<Image Source="severity_4.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity4Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_4.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="2">
<Image Source="severity_3.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity3Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_3.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="3">
<Image Source="severity_2.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity2Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_2.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="4">
<Image Source="severity_1.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding Severity1Opacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="severity_1.png" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
<!--Status-->
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Text="STATUS" HorizontalTextAlignment="Start" VerticalTextAlignment="Center" TextColor="White" Style="{StaticResource Labelfont}" />
<Label Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" FontSize="Micro" Text="STATUS" HorizontalTextAlignment="End" VerticalTextAlignment="Center" TextColor="White"
Style="{StaticResource Labelfont}" IsVisible="True" />
<StackLayout Grid.Row="3" Grid.Column="1" Orientation="Horizontal" Spacing="0">
<Image Source="statusUnresolved.png" HorizontalOptions="Center"
VerticalOptions="Center" HeightRequest="40" Opacity="{Binding StatusUnresolvedOpacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="statusUnresolved.png"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="3" Grid.Column="2" Orientation="Horizontal" Spacing="4">
<Image Source="statusInProgress.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="{Binding StatusInProgressOpacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="statusInProgress.png"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
<StackLayout Grid.Row="3" Grid.Column="3" Orientation="Horizontal" Spacing="4">
<Image Source="statusDone.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="{Binding StatusDoneOpacity}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnStatusClickedCommand}" CommandParameter="statusDone.png"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</Grid>
<!--Date Created-->
<Label Text="TIME AND DATE: " Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" BackgroundColor="Black" Padding="2">
<StackLayout Orientation="Horizontal" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Spacing="0" Margin="0" Padding="0"
BackgroundColor="Black" HeightRequest="40">
<Label Text=" " Style="{StaticResource Labelfont}" TextColor="White" BackgroundColor="Black"
Margin="1" />
<Label Text="{Binding CreatedEx, Converter={StaticResource DateToTextConverter}}"
Style="{StaticResource Labelfont}" TextColor="White" BackgroundColor="Black"
VerticalOptions="Center" />
</StackLayout>
</Frame>
<!--REPORTED BY-->
<Label Text="REPORTED BY: " Style="{StaticResource Labelfont}" TextColor="White" />
<Frame OutlineColor="#FBB040" BackgroundColor="Black" Padding="2">
<StackLayout Orientation="Horizontal" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" Spacing="0" Padding="1" BackgroundColor="Black"
HeightRequest="40">
<Label Text=" " Style="{StaticResource Labelfont}" TextColor="White" BackgroundColor="Black" />
<Label Text="{Binding CreatedByEx}" Style="{StaticResource Labelfont}"
TextColor="White" BackgroundColor="Black" VerticalOptions="Center" />
</StackLayout>
</Frame>
<!--Map View-->
<Grid>
<Grid.BindingContext>
<maps:TkMapPageModel/>
</Grid.BindingContext>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
<RowDefinition Height="40" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Label Grid.Column="1" Grid.Row="0" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"
Text="Tap and hold on map to set/move pin" Font="Large" />
<StackLayout Grid.Column="1" Grid.Row="1" VerticalOptions="FillAndExpand">
<RelativeLayout x:Name="MapRelativeLayout" VerticalOptions="FillAndExpand" HeightRequest="920" WidthRequest="300" />
</StackLayout>
<StackLayout Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="3" Orientation="Vertical" Spacing="0">
<Label Text="{Binding MapText}" VerticalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White" />
</StackLayout>
</Grid>
<Button Text="Submit"
HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand" Command="{Binding SubmitCommand}"
BackgroundColor="#FBB040" />
</StackLayout>
</ScrollView>
<!--Bottom Navigation Bar-->
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<StackLayout Grid.ColumnSpan="3" Grid.Row="1" Orientation="Horizontal"
HorizontalOptions="FillAndExpand" Spacing="5" BackgroundColor="White">
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Image Source="photo2.png" WidthRequest="100" HeightRequest="100" HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
</Image>
</StackLayout>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Image Source="photo2.png" WidthRequest="100" HeightRequest="100" HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
</Image>
</StackLayout>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Image Source="showmap.png" WidthRequest="100" HeightRequest="60" HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand">
</Image>
</StackLayout>
</StackLayout>
</Grid>
</Grid>
正如我重复的那样,它在从 imagegallerypagemodel 添加而不是从其他 class IssuePageModel
添加时有效public class ImageGalleryControl : ScrollView
{
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create<ImageGalleryControl, IList>(
view => view.ItemsSource,
default(IList),
BindingMode.TwoWay,
propertyChanging: (bindableObject, oldValue, newValue) => {
((ImageGalleryControl)bindableObject).ItemsSourceChanging();
},
propertyChanged: (bindableObject, oldValue, newValue) => {
((ImageGalleryControl)bindableObject).ItemsSourceChanged(bindableObject, oldValue, newValue);
}
);
public IList ItemsSource
{
get
{
return (IList)GetValue(ItemsSourceProperty);
}
set
{
SetValue(ItemsSourceProperty, value);
}
}
Images
在你的模型中是一个 ObservableCollection
,它很像一个列表。当您添加图像时,您不会点击 set
因为您没有更改集合,而是添加到现有集合中。这是正确的方法... ObservableCollection
包含 INotifyCollectionChanged
接口,这意味着有一个 CollectionChanged
事件你可以订阅并监听变化。在任何项目源中使用 XAML 绑定时,它应该会自动为您侦听和处理此事件,但在后面的代码中或您自己代码中的任何地方,您很可能需要这样做。
请记住,集合引用也可能发生变化,因此您也需要对其进行处理。下面是如何正确处理模型之间 ObservableCollection
的示例。
public class ExampleModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<string> names = new ObservableCollection<string>();
public ObservableCollection<string> Names
{
get => names;
set
{
names = value;
//Only called if I change the collection reference i.e. make a new ObservableCollection or assign it to another exising reference.
//Not called adding or removing items from existing collection.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Names)));
}
}
}
.....
public class ExampleViewModel : INotifyPropertyChanged
{
private readonly ExampleModel ExampleModel;
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<string> names = new ObservableCollection<string>();
public ExampleViewModel()
{
ExampleModel = new ExampleModel();
ExampleModel.PropertyChanged += ExampleModel_PropertyChanged;
Names = ExampleModel.Names;
if (Names != null) Names.CollectionChanged += Names_CollectionChanged;
}
private void ExampleModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(ExampleModel.Names):
//Here we reassign the entire collection if it changes.
if (Names != null) Names.CollectionChanged -= Names_CollectionChanged;
Names = ExampleModel.Names;
if (Names != null) Names.CollectionChanged += Names_CollectionChanged;
break;
}
}
private void Names_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (var item in e.OldItems) Names.Remove((string)item);
foreach (var item in e.NewItems) Names.Add((string)item);
}
public ObservableCollection<string> Names
{
get => names;
set
{
names = value;
//Only called if I change the collection reference i.e. make a new ObservableCollection or assign it to another exising reference.
//Not called adding or removing items from existing collection.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Names)));
}
}
}
注意:这个例子只是为了让你更清楚地了解它是如何工作的,可能不是实现这两者的最简洁的方法。如果知道它们都是 ObservableCollections 那么那很好,但至少我们应该假设它们是 IEnumerable 并且处理方式略有不同。无论哪种方式......但是你需要在你的代码中手动处理它并且 XAML 应该在绑定到 ItemsSource 时为你处理它。