- 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/
情况我想使用 ui-date 在我的应用程序中设置/编辑日期。我使用最新稳定版本的 Angular、Angular-UI、JQuery-UI 等。 问题一旦使用日期选择器选择了日期,我的模型中的日期将
编辑: jQuery UI 可选择小部件内置了一个回调,stop,我需要知道如何以编程方式触发此事件。 (措辞不佳)我已将事件监听器附加到 jQuery UI Selectable Widget 。如
我正在尝试建立一个下一个JS与尾风用户界面提供的反应组件的网络应用程序。顺风用户界面是在幕后使用无头用户界面。。默认情况下,Next JS将构建服务器端组件,除非您在页面顶部添加“使用客户端”。不幸的
我正在尝试建立一个下一个JS与尾风用户界面提供的反应组件的网络应用程序。顺风用户界面是在幕后使用无头用户界面。。默认情况下,Next JS将构建服务器端组件,除非您在页面顶部添加“使用客户端”。不幸的
我正在尝试应用这个 SlickGrid 示例: http://mleibman.github.com/SlickGrid/examples/example4-model.html 到我自己的网络项目。
我想整理我的 Schemas为我的实体类生成,DTO 类位于 Springdoc ui . 我可以对 tags 进行排序和 operations通过以下配置 yml文件,但我的模式不是按排序顺序排列的
有谁知道阻止 ui-sref 重新加载状态的方法吗? 我无法通过“$stateChangeStart”事件执行此操作,因为 ui-sref 仅更改参数而不更改状态名称。 我的左边是书单,左边是书的详细
我正在 jquery ui 对话框中使用 jquery ui 自动完成小部件。当我输入搜索文本时,文本框缩进(ui-autocomplet-loading)但不显示任何建议。 var availabl
我正在尝试将 Kendo UI MVVM 框架与 Kendo UI 拖放机制结合使用;但我很难找到如何将数据从 draggable 对象中删除。 我的代码是这样的...... var viewMode
Kendo UI Web 和 Kendo UI Core 之间有什么区别 https://www.nuget.org/packages/KendoUIWeb http://www.nuget.org/
我正在尝试将 Kendo UI MVVM 框架与 Kendo UI 拖放机制结合使用;但是我很难找到如何从 draggable 对象中删除数据。 我的代码是这样的…… var viewModel =
使用 Angular JS - UI 路由器,我需要从我的父 View project.details 到我的 subview project.details.tasks 进行通信。我的 subvie
KendoUI 版本 2013.3.1119使用 Kendo MVVM 我有一个我构建的颜色选择器,它使用平面颜色选择器和使用调色板的颜色选择器。它们都可以正常运行,但平面颜色选择器的布局已关闭, s
我在非 UI 线程上,我需要创建并显示一个 SaveDialog。但是当我尝试显示它时:.ShowDialog() 我得到: "An unhandled exception of type 'Syst
我正在试验 jquery-ui 并查看和克隆一些示例。在一个示例(自动完成的组合框)中,我看到一个带有 ui-widget 类的 anchor (a) 元素,它与包含的 css 文件中的 .ui-wi
我需要返回一个 UI 列表,我用这个方法: getList(): Observable { return this.httpClient.get("/api/listui").pipe
我有 ui-grids在 angular-ui-tabs ,它们位于 ng-if 中以避免呈现问题。如果有更多数据并且网格进入滚动模式,则单击选项卡时数据会完全消失。我相信这是一个 ui-grids-
这似乎是一个通用的问题,与其他几个 React 开源框架相比,我真的很喜欢 Material ui 的可扩展性。 问题 “@material-ui/core”和“@material-ui/lab”中的
我有一个根页面(index.html),带有侧边栏(“菜单”)和主要内容 div(“主”),因此有两个 ui-view div - 一个称为“菜单”,一个称为“主”。 当主要内容区域有网站列表 (/s
有人在http://jsfiddle.net/hKYWr/上整理了一个很好的 fiddle 。关于使用 angular-ui 和 jqueryui sortable 来获得良好的可排序效果。 如何在两
我是一名优秀的程序员,十分优秀!