- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 Xamarin 表单上有一个适用于 Android 和 iOS 的跨平台应用程序。
在某些 View 中,我使用 ObservableCollection 作为 ListView
的源。
在 ListView 中,有一些按钮可供用户交互和更改 UI。
在 Android 上一切正常,但当我在 iOS 上测试时,只有单击 1 次后才会执行更改。
我使用 MVVM 架构来满足我的需求,它在 Android 上运行得很好。唯一的问题是 iPhone。
C# 代码:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ConvidarAmigosEmail : ContentView
{
public ConvidarAmigosEmail ()
{
BindingContext = new ConvidarAmigosEmailViewModel();
InitializeComponent ();
}
private void ListaEmail_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null) return;
listaEmail.SelectedItem = null;
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
}
}
public class ConvidarAmigosEmailViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<Contacto> _contactosComEmail;
public ObservableCollection<Contacto> ContactosComEmail { get => _contactosComEmail; set { _contactosComEmail = value; OnPropertyChanged(nameof(ContactosComEmail)); } }
public ICommand SeleccionarContacto
{
get => new Command<Contacto>((contacto) =>
{
if (!contacto.Seleccionado)
{
contacto.Seleccionado = !contacto.Seleccionado;
contacto.Opcao = AppResource.Seleccionado;
ContactosSeleccionadosEmail.Add(contacto);
}
else
{
contacto.Seleccionado = !contacto.Seleccionado;
contacto.Opcao = AppResource.Select;
ContactosSeleccionadosEmail.Remove(contacto);
}
});
}
public ICommand SeleccionarTodos
{
get => new Command(() =>
{
if (ContactosComEmail.Count != ContactosSeleccionadosEmail.Count)
{
ContactosSeleccionadosEmail.Clear();
foreach (var obj in ContactosComEmail)
{
obj.Seleccionado = true;
obj.Opcao = AppResource.Seleccionado;
ContactosSeleccionadosEmail.Add(obj);
}
}
else
{
ContactosSeleccionadosEmail.Clear();
foreach (var obj in ContactosComEmail)
{
obj.Seleccionado = false;
obj.Opcao = AppResource.Select;
}
}
});
}
public List<Contacto> ContactosSeleccionadosEmail { get; set; } = new List<Contacto>();
private string _textoSelectTodos = AppResource.SelTodos;
public string TextoSelectTodos
{
get
{
if (ContactosSeleccionadosEmail.Count == ContactosComEmail.Count)
{
_textoSelectTodos = AppResource.Anull;
OnPropertyChanged(nameof(TextoSelectTodos));
return _textoSelectTodos;
}
_textoSelectTodos = AppResource.SelTodos;
OnPropertyChanged(nameof(TextoSelectTodos));
return _textoSelectTodos;
}
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged == null)
return;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ConvidarAmigosEmailViewModel()
{
ContactosComEmail = new ObservableCollection<Contacto>();
ObterContactos();
}
#region ObterContactos
/*
Params Entrada => nenhum
Params Saída => nenhum
Lógica => Passo 1 : Acede a lista de contactos do telefone e extrai os dados;
Passo 2 : Coloca os contactos com email na variável ContactosE; os que não têm email em ContactosT
Passo 3 : ContentLoader para aceder ao caminho real do ficheiro de imagem (foto) do contacto;
Passo 4 : Adiciona os contactos com Email a uma lista da classe "Contacto", Contactos#. Os sem email para ContactosT
Plugins : Obter permissoes => https://www.nuget.org/packages/plugin.permissions/;
Aceder aos contactos =>
*/
public async void ObterContactos()
{
//verifica se aplicacao tem permissao pra aceder a lista de contactos
var statusPermissao = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Contacts);
//requisitar permissao
if (statusPermissao == PermissionStatus.Unknown)
{
var resposta = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Contacts);
statusPermissao = resposta[Permission.Contacts];
}
if (statusPermissao == PermissionStatus.Denied)
{
var op = await App.Current?.MainPage?.DisplayAlert(AppResource.contactosNegados, AppResource.SemFuncionalidade, AppResource.Definicoes, AppResource.MaisTarde);
if (op == true)
{
CrossPermissions.Current.OpenAppSettings();
}
else
{
await App.Current?.MainPage?.Navigation?.PopAsync();
}
}
if (statusPermissao == PermissionStatus.Granted)
{
var contactos = await Plugin.ContactService.CrossContactService.Current.GetContactListAsync();
//contactos com email
var contactosE = contactos.Where(x => x.Email != null).OrderBy(x => x.Name).ToList();
//imagem inicial de cada contacto, caso esta não tenha imagem de perfil.
var aux = ImageSource.FromResource("KiaiDay.Images.user.png");
foreach (var c in contactosE)
{
aux = ImageSource.FromResource("KiaiDay.Images.user.png");
if (c.PhotoUri != null)
{
//caso tenho imagem de perfil, aceder ao caminho real no ficheiro e extrair a imagem
var contentLoader = DependencyService.Get<IContentLoader>();
var uri = new Uri(c.PhotoUri);
aux = contentLoader.LoadFromContentUri(uri);
}
ContactosComEmail.Add(
new Contacto()
{
Email = c.Email,
Foto = aux,
Numero = c.Number,
Nome = c.Name,
Opcao = AppResource.Select
});
}
}
else
{
//await App.Current?.MainPage?.DisplayAlert(AppResource.contactosNegados, AppResource.SemFuncionalidade, AppResource.ok);
//App.Current?.MainPage?.Navigation?.PopAsync();
}
}
#endregion
}
xaml 代码:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KiaiDay.Views.PosLogin.ConvidarAmigosEmail" x:Name="pagina"
xmlns:FFIL="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:FFT="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations">
<ContentView.Content>
<Grid BackgroundColor="White" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="7*"/>
</Grid.RowDefinitions>
<Grid ColumnSpacing="0" Grid.Row="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Frame Grid.Row="0" Grid.Column="2" Padding="8" BackgroundColor="#f2f2f2" Margin="-25,0,0,0"
HorizontalOptions="CenterAndExpand" VerticalOptions="Center" BorderColor="LightGray" HasShadow="False">
<Frame.CornerRadius>
<OnPlatform Android="80" iOS="10"/>
</Frame.CornerRadius>
<Label Grid.ColumnSpan="2" Text="{Binding TextoSelectTodos}" FontFamily="{StaticResource RegularFont}" TextColor="{Binding CorSelectTodos}" FontSize="10" VerticalOptions="FillAndExpand" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Command="{Binding SeleccionarTodos}"/>
</Frame.GestureRecognizers>
</Frame>
</Grid>
<ListView SeparatorColor="LightGray" ItemsSource="{Binding ContactosComEmail}" HasUnevenRows="True" x:Name="listaEmail"
Margin="30,0,30,0" ItemSelected="ListaEmail_ItemSelected" IsGroupingEnabled="False" Grid.Row="1" CachingStrategy="RetainElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid ColumnSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="3"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="3"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<FFIL:CachedImage Grid.Row="1" Grid.Column="0" Grid.RowSpan="2"
Source="{Binding Foto}" DownsampleToViewSize="True" BitmapOptimizations="False"
Aspect="AspectFit" RetryCount="0" RetryDelay="250" HeightRequest="50"
LoadingPriority="Highest" HorizontalOptions="Center" VerticalOptions="Center"
FadeAnimationForCachedImages="False" WidthRequest="50">
<FFIL:CachedImage.Transformations>
<FFT:CircleTransformation/>
</FFIL:CachedImage.Transformations>
</FFIL:CachedImage>
<Label Grid.Row="1" Grid.Column="1" Text="{Binding Nome}" FontFamily="{StaticResource RegularFont}" TextColor="#3c3c3b" LineBreakMode="TailTruncation"/>
<Label Grid.Row="2" Grid.Column="1" Text="{Binding Email}" FontFamily="{StaticResource RegularFont}" TextColor="#3c3c3b" LineBreakMode="TailTruncation"/>
<Frame Grid.Row="1" Grid.Column="2" Padding="8" BackgroundColor="#f2f2f2" Grid.RowSpan="2"
HorizontalOptions="CenterAndExpand" VerticalOptions="Center" BorderColor="LightGray" HasShadow="False">
<Frame.CornerRadius>
<OnPlatform Android="80" iOS="10"/>
</Frame.CornerRadius>
<Grid HorizontalOptions="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<FFIL:CachedImage Source="{Binding Icone}" HeightRequest="8" WidthRequest="8" BackgroundColor="Transparent" Grid.Column="0"
VerticalOptions="Center" LoadingPriority="Highest" RetryCount="0" RetryDelay="250" DownsampleToViewSize="True" BitmapOptimizations="False"/>
<Label Text="{Binding Opcao}" FontFamily="{StaticResource RegularFont}" FontSize="8" TextColor="{Binding Cor}" Grid.Column="1" VerticalOptions="Center"/>
</Grid>
<Frame.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Command="{Binding Source={x:Reference pagina},Path=BindingContext.SeleccionarContacto}" CommandParameter="{Binding .}" Tapped="TapGestureRecognizer_Tapped"/>
</Frame.GestureRecognizers>
</Frame>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ContentView.Content>
</ContentView>
我希望 ObservableCollection 能够更新 iOS 上的 UI,而无需单击。
编辑:使用的插件 => https://github.com/jamesmontemagno/PermissionsPlugin ; https://github.com/jamesmontemagno/ContactsPlugin ;
模型定义
public class Contacto : INotifyPropertyChanged, IEntity
{
public event PropertyChangedEventHandler PropertyChanged;
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Nome { get; set; }
public string Email { get; set; }
public string Numero { get; set; }
[Ignore]
public ImageSource Foto { get; set; }
private ImageSource _icone = ImageSource.FromFile("mais.png");
[Ignore] public ImageSource Icone
{
get
{
if (Seleccionado)
{
_icone = ImageSource.FromFile("certo.png");
OnPropertyChanged(nameof(Icone));
return _icone;
}
_icone = ImageSource.FromFile("mais.png");
OnPropertyChanged(nameof(Icone));
return _icone;
}
set
{
_icone = value;
OnPropertyChanged(nameof(Icone));
}
}
private string _opcao;
[Ignore]
public string Opcao
{
get
{
return _opcao;
}
set
{
_opcao = value;
OnPropertyChanged(nameof(Opcao));
}
}
private bool _seleccionado = false;
public bool Seleccionado
{
get
{
return _seleccionado;
}
set
{
_seleccionado = value;
OnPropertyChanged(nameof(Seleccionado));
}
}
private Color _cor = Color.FromHex("#3c3c3b");
[Ignore]
public Color Cor
{
get
{
if (Seleccionado)
{
_cor = Color.FromHex("#4297d3");
OnPropertyChanged(nameof(Cor));
return _cor;
}
_cor = Color.FromHex("#3c3c3b");
OnPropertyChanged(nameof(Cor));
return _cor;
}
set
{
_cor = value;
OnPropertyChanged(nameof(Cor));
}
}
#region INotifyPropertyChanged Implementation
void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged == null)
return;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
编辑2:更改 View 模型的构造函数后, View 正在更新,但我无法做任何其他事情。好像被屏蔽了。
public ConvidarAmigosEmailViewModel()
{
ContactosComEmail = new ObservableCollection<Contacto>();
Task.Run(async () => { await ObterContactos(); });
}
EDIT3:在花了很多时间试图弄清楚发生了什么之后,我得出的结论是问题出在这部分代码上:
<Frame Grid.Row="1" Grid.Column="2" Padding="8" BackgroundColor="#f2f2f2" Grid.RowSpan="2" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" HasShadow="False">
<Frame.CornerRadius>
<OnPlatform Android="80" iOS="10"/>
</Frame.CornerRadius>
<Grid HorizontalOptions="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<FFIL:CachedImage Source="{Binding Icone}" HeightRequest="8" WidthRequest="8" BackgroundColor="Transparent" Grid.Column="0"
DownsampleToViewSize="True" BitmapOptimizations="False" Aspect="AspectFit" RetryCount="0" RetryDelay="250"
LoadingPriority="Highest" HorizontalOptions="Center" VerticalOptions="Center" FadeAnimationForCachedImages="False"/>
<Label Text="{Binding Opcao}" FontFamily="{StaticResource RegularFont}" FontSize="8" TextColor="{Binding Cor}" Grid.Column="1" VerticalOptions="Center"/>
</Grid>
<Frame.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Command="{Binding Source={x:Reference pagina},Path=BindingContext.SeleccionarContacto}" CommandParameter="{Binding .}"/>
</Frame.GestureRecognizers>
</Frame>
我不知道为什么会发生这种情况...
最佳答案
我认为这已经足够了,没有调试器和源代码就很困难。
ConvidarAmigosEmail.xaml
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ConvidarAmigosEmail : ContentView
{
public ConvidarAmigosEmailViewModel ViewModel { get; set; }
public ConvidarAmigosEmail ()
{
ViewModel = new ConvidarAmigosEmailViewModel();
InitializeComponent ();
BindingContext = new ConvidarAmigosEmailViewModel();
}
public async override OnAppearing()
{
// will be good that you show loading icon while processing data
await ViewModel.LoadData();
}
private void ListaEmail_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null) return;
listaEmail.SelectedItem = null;
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
}
}
View 模型创建
public ConvidarAmigosEmailViewModel()
{
ContactosComEmail = new ObservableCollection<Contacto>();
}
public async Task LoadData()
{
await ObterContactos();
}
ObterContactos 内部
//imagem inicial de cada contacto, caso esta não tenha imagem de perfil.
var aux = ImageSource.FromResource("KiaiDay.Images.user.png");
var ListContactos = new List<Contacto>();
foreach (var c in contactosE)
{
aux = ImageSource.FromResource("KiaiDay.Images.user.png");
if (c.PhotoUri != null)
{
//caso tenho imagem de perfil, aceder ao caminho real no ficheiro e extrair a imagem
var contentLoader = DependencyService.Get<IContentLoader>();
var uri = new Uri(c.PhotoUri);
aux = contentLoader.LoadFromContentUri(uri);
}
// Add method inside foreach generate too many innecesary property changed
// notifications
ListContactos.Add(
new Contacto()
{
Email = c.Email,
Foto = aux,
Numero = c.Number,
Nome = c.Name,
Opcao = AppResource.Select
});
}
ObterContactos = new ObservableCollection<Contacto>(ListContactos);
}
else
...
关于c# - 为什么 ObservableCollection 更新 Android 上的 UI 而不是 iOS?[待定],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56804410/
这是一个有趣的案例,我无法在网上找到任何信息。我正在尝试创建一个网格,需要将 ObservableCollection 的 ObservableCollection 绑定(bind)到它。想象这样一个
如何复制ObservableCollection项目到另一个 ObservableCollection没有引用第一个集合?这里ObservableCollection影响两个集合的项目值更改。 代码
public class Alpha { public ObservableCollection Items { get; set; } public Alpha() {
我只是想知道如何拥有父集合的子集合? 例如, 我已经有一个 ObservableCollection 产品,它正在添加并正确绑定(bind)到 XAML。但是,现在我需要另一个包含产品项目的 Obse
我对 Silverlight 体验相对较新,我正在尝试创建一个带有 DomainService 的 MVVM 应用程序,该应用程序将 POCO 作为模型返回。我有一个 UserControl,它有一个
查看 Microsoft 站点上的 Windows 运行时引用,我能找到的唯一相关集合是 IObservableVector 。 .NET Projection ObservableCollectio
我正在尝试获取值“thisValueIwant”。有没有可能如此容易地获得这个值(value)?或者也许这两个 ObservableCollection 有另一种解决方案 public class F
我有一个 ObserveableCollection,其中包含另一个 ObserveableCollection。在我的 WPF 中,我设置了对 Persons.Lectures 的绑定(bind)。
我有一个包含 20 个项目(图像)和按钮(“下一个”)的 observablecollection。我如何获得像 observablecollection.next() 和 observablecol
我有一个 ObservableCollection . T 有一个 ToString() 方法。我想做的是转换 ObservableCollection至 ObservableCollection .
我有一个 DataGrid,它绑定(bind)到 ViewModel 中的一个 ObservableCollection。这是一个搜索结果DataGrid。问题是,在我更新搜索结果 Observabl
有一堆ObservableCollection Result并要求将它们全部组合成另一个 ObservableCollection AllResults所以我可以在 listview 中显示它. 只是
哪个是保存我的数据的更好解决方案,还是取决于某些条件? 示例情况 1: 您需要显示一个数据列表,选择后可以在新窗口中修改。 示例情况 2: 您需要显示可以在此列表中修改的数据列表。 最佳答案 当您使用
从 xml 中执行 ViewModel 的最佳方法是什么:
所以我有一个 BaseClass 以及继承自基类的几个子类 ChildClass1 ChildClass2 我有ObservableCollections需要就地排序的子类,我无法创建新的 Obser
我为 ObservableCollection 构建了一个简单的扩展方法 AddRange: using System; using System.Collections.Generic; using
我的情况是,我有“tablegenerateModel”类的 ObservableCollection,该类进一步包含“column_Data”类的 ObservableCollection,并且这个
我将有一个 7 个小“购物 list ”,然后是一个包含 7 个小 list 中所有项目的大 list 。 是否可以使用 databind 和 observablecollection,以便从小列表中
当所述 ObservableCollection 从 View 模型公开时,我无法找到正确的绑定(bind)语法来绑定(bind) ObservableCollection 中包含的项目的属性。 当我
我有以下类(class),效果很好 public class RemoteSource { ObservableCollection remote; string[] _servers
我是一名优秀的程序员,十分优秀!