В моей среде код не работал в этом URL http://motzcod.es/post/94643411707/enhancing-xamarinforms-listview-with-grouping .
Код, который не работает, здесь
var partnersSorted = from item in Partners
orderby item.UserName
group item by item.UserNameSort into PartnersGroup
select new Grouping(PartnersGroup.Key, PartnersGroup);
MonkeysGrouped = new ObservableCollection>(partnersSorted);
Итак, я изменил код.
var sortedPartners = Partners.OrderBy(x => x.UserName).GroupBy(y => y.UserNameSort);
foreach (var item in sortedPartners)
{
PartnersGrouped.Add(new PartnersGrouping(item.Key, Partners.Where(x=>x.UserNameSort == item.Key)));
}
Вы можете видеть вот так.
[ https://i.stack.imgur.com/BswPq.png] [1]
вот мои все скрипты
Элемент является партнером
Item.cs
using System;
namespace NewHeats.Models
{
public class Item
{
public string Id
{
get;
set;
}
public string UserName
{
get;
set;
}
public DateTime RegisterDate
{
get;
set;
}
public string Field
{
get;
set;
}
public string Password
{
get;
set;
}
public int Heats
{
get;
set;
}
public string UserNameSort
{
get
{
if (string.IsNullOrWhiteSpace(UserName) || UserName.Length == 0)
return "?";
return UserName[0].ToString().ToUpper();
}
}
}
}
PartnersGrouping.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace NewHeats.Models
{
public class PartnersGrouping : ObservableCollection
{
public K Key { get; private set; }
public PartnersGrouping(K key,IEnumerable items)
{
Key = key;
foreach (var item in items)
{
this.Items.Add(item);
}
}
}
}
PartnersViewModel.cs
using System;
using System.Windows.Input;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Xamarin.Forms;
using NewHeats.Models;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Linq;
using System.Diagnostics.Contracts;
namespace NewHeats.ViewModels
{
public class PartnersViewModel : BaseViewModel
{
public Item Me
{
get;
set;
}
public ObservableCollection- Partners { get; set; }
public ObservableCollection
> PartnersGrouped { get; set; }
public Item SelectedPartner { get; set; }
public Command LoadPartnersCommand { get; set; }
public PartnersViewModel()
{
Title = "Partners";
Partners = new ObservableCollection- ();
PartnersGrouped = new ObservableCollection
>();
LoadPartnersCommand = new Command(async() =>await ExecuteLoadPartnersCommand());
}
async Task ExecuteLoadPartnersCommand()
{
Contract.Ensures(Contract.Result() != null);
if (IsBusy)
return;
IsBusy = true;
try
{
Me = await MockUsrDataStore.GetItemAsync("naoto");
Partners.Clear();
var allfriends = await MockFriDataStore.GetItemsAsync(true);
var myFriends = allfriends.Where(x => x.MyId == Me.Id);
var allUsers = await MockUsrDataStore.GetItemsAsync(true);
foreach (var item in myFriends)
{
var partner = allUsers.FirstOrDefault(x => x.Id == item.FriendId);
if (partner!=null)
{
Partners.Add(partner);
}
}
var sortedpartners = Partners.OrderBy(x => x.UserName).GroupBy(y => y.UserNameSort);
foreach (var item in sortedpartners)
{
PartnersGrouped.Add(new PartnersGrouping(item.Key, Partners.Where(x=>x.UserNameSort == item.Key)));
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
}
PartnerPage.xaml
#2196F3
#96d1ff
#999999
Спасибо !!
Вы могли включить дублированный код в CodeableEnumHelper
класс:
public class CodeableEnumHelper {
public static CodeableEnum getByCode(String code, CodeableEnum[] values) {
for (CodeableEnum e : values) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
return null;
}
}
Каждый CodeableEnum
класс должен был бы все еще реализовать getByCode
метод, но фактическая реализация метода была, по крайней мере, централизована к единственному месту.
public enum IMType implements CodeableEnum {
...
public IMType getByCode(String code) {
return (IMType)CodeableEnumHelper.getByCode(code, this.values());
}
}
В Вашем конкретном случае getCode () / getByCode (Код строки) методы кажется очень закрытым (эвфемистически говорящий) к поведению toString () / valueOf (Строковое значение) методы, предоставленные всем перечислением. Почему Вы не хотите использовать их?
Почти настолько близко, как я добрался до того, что Вы хотите, должен был создать шаблон в IntelliJ, который 'реализует' универсальный код (использующий valueOf перечисления (Имя строки)). Не прекрасный, но работает вполне хорошо.
Если Вы действительно хотите наследование, не забывайте, что Вы можете реализовывать перечислимый шаблон сами , как в плохие старые дни Java 1.4.
Как насчет статического общего метода? Вы могли снова использовать его из getByCode своего перечисления () методы или просто использовать его непосредственно. Я всегда пользовательские целочисленные идентификаторы для моих перечислений, таким образом, мой getById () метод только имеет, действительно делаю это: возвращаемые значения () [идентификатор]. Это намного быстрее и более просто.
Я не думаю, что это возможно. Однако Вы могли использовать valueOf перечисления (Имя строки) метод, если бы Вы собирались использовать имя перечисления значений в качестве своего кода.
Создайте безопасный с точки зрения типов служебный класс, который загрузит перечисления кодом:
интерфейс сводится:
public interface CodeableEnum {
String getCode();
}
служебный класс:
import java.lang.reflect.InvocationTargetException;
public class CodeableEnumUtils {
@SuppressWarnings("unchecked")
public static <T extends CodeableEnum> T getByCode(String code, Class<T> enumClass) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
T[] allValues = (T[]) enumClass.getMethod("values", new Class[0]).invoke(null, new Object[0]);
for (T value : allValues) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}
}
использование демонстрации тестового сценария А:
import junit.framework.TestCase;
public class CodeableEnumUtilsTest extends TestCase {
public void testWorks() throws Exception {
assertEquals(A.ONE, CodeableEnumUtils.getByCode("one", A.class));
assertEquals(null, CodeableEnumUtils.getByCode("blah", A.class));
}
enum A implements CodeableEnum {
ONE("one"), TWO("two"), THREE("three");
private String code;
private A(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
}
Теперь Вы только копируете getCode () метод и getByCode (), метод находится в одном месте. Могло бы быть хорошо обернуть все исключения в единственный RuntimeException также:)
К сожалению, я не думаю, что существует способ сделать это. Ваш лучший выбор был бы про успешно, чтобы должным быть сдаться в перечислениях в целом и использовать стандартный класс дополнительные и статические участники. Иначе привыкните к дублированию того кода. Извините.
У меня была подобная проблема с компонентом локализации, который я записал. Мой компонент разработан для доступа к локализованным сообщениям с перечислимыми константами что индекс в пакет ресурса, не тяжелая проблема.
я нашел, что копировал и вставлял тот же "шаблонный" код перечисления повсеместно. Моим решением избежать дублирования является генератор кода, который принимает конфигурационный XML-файл с перечислимыми постоянными именами и конструктором args. Вывод является исходным кодом Java с "дублированными" поведениями.
Теперь, я поддерживаю конфигурационные файлы и генератор, не весь дублированный код. Везде у меня был бы перечислимый исходный код, существует теперь файл конфигурации XML. Мои сценарии сборки обнаруживают устаревшие сгенерированные файлы и вызывают генератор кода для создания перечислимого кода.
Вы видите этот компонент здесь . Шаблон, который я копировал и вставлял, факторизуется в таблица стилей XSLT . генератор кода выполнения преобразование таблицы стилей. входной файл довольно краток по сравнению со сгенерированным перечислимым исходным кодом.
HTH,
Greg
Абстрактные перечисления потенциально очень полезны (и в настоящее время не позволенные). Но предложение и прототип существуют, если требуется лоббировать кого-то в Sun для добавления его:
http://freddy33.blogspot.com/2007/11/abstract-enum-ricky-carlson-way.html
RFE Sun:
Убрать код dave:
public class CodeableEnumHelper {
public static <E extends CodeableEnum> E getByCode(
String code, E[] values
) {
for (E e : values) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
return null;
}
}
public enum IMType implements CodableEnum {
...
public IMType getByCode(String code) {
return CodeableEnumHelper.getByCode(code, values());
}
}
Или более эффективно:
public class CodeableEnumHelper {
public static <E extends CodeableEnum> Map<String,E> mapByCode(
E[] values
) {
Map<String,E> map = new HashMap<String,E>();
for (E e : values) {
map.put(e.getCode().toLowerCase(Locale.ROOT), value) {
}
return map;
}
}
public enum IMType implements CodableEnum {
...
private static final Map<String,IMType> byCode =
CodeableEnumHelper.mapByCode(values());
public IMType getByCode(String code) {
return byCode.get(code.toLowerCase(Locale.ROOT));
}
}
Кажется на фактическую реализацию информации о типе выполнения. Java обеспечивает это как функцию языка.
я предлагаю, чтобы Вы искали RTTI или отражение.
Другим решением было бы не помещать ничего в само перечисление, а просто предоставить двунаправленную карту Enum <-> Code для каждого перечисления. Вы могли бы, например, используйте для этого ImmutableBiMap из Google Collections.
Таким образом, никакого дублирования кода не будет.
Пример:
public enum MYENUM{
VAL1,VAL2,VAL3;
}
/** Map MYENUM to its ID */
public static final ImmutableBiMap<MYENUM, Integer> MYENUM_TO_ID =
new ImmutableBiMap.Builder<MYENUM, Integer>().
put(MYENUM.VAL1, 1).
put(MYENUM.VAL2, 2).
put(MYENUM.VAL3, 3).
build();
На мой взгляд, это был бы самый простой способ, без отражения и без добавления дополнительной оболочки к вашему перечислению.
Вы создаете интерфейс, который реализует ваше перечисление:
public interface EnumWithId {
public int getId();
}
Затем во вспомогательном классе вы просто создаете метод, подобный этому:
public <T extends EnumWithId> T getById(Class<T> enumClass, int id) {
T[] values = enumClass.getEnumConstants();
if (values != null) {
for (T enumConst : values) {
if (enumConst.getId() == id) {
return enumConst;
}
}
}
return null;
}
Затем этот метод можно использовать следующим образом:
MyUtil.getInstance().getById(MyEnum.class, myEnumId);