сделать или объявить глобальную переменную ObservableCollection <a>, где a = анонимный тип - PullRequest
1 голос
/ 03 апреля 2012

Я хочу установить текстовый вид списка, равный наблюдаемой коллекции, чтобы изменения в коллекции могли отразиться на моем просмотре списка. Я создаю наблюдаемую коллекцию как:

public static ObservableCollection<T> ToObservableCollection<T>(IEnumerable<T> enumeration)
{
     return new ObservableCollection<T>(enumeration);
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{

           Entities.DatabaseModel m = new Entities.DatabaseModel();
           var q = from t in m.TimeSheet                            
                    join emp in m.Employees on t.idEmployee equals emp.id
                    where emp.id == CurrentEmploye.id
                    select new
                    {
                        firstName = emp.firstName,
                        lastName = emp.lastName,
                        position = emp.position,
                        clockInDate = t.clockInDate,
                        clockOutDate = t.clockOutDate,
                    };
           // here I create the observablecollection!!!!!!!!!!!!!!
           listView1.DataContext = ToObservableCollection(q); 
}

Теперь моя проблема в том, что если я хочу добавить элементы в ObservableCollection, как я могу это сделать? Если я сделаю listView1.DataContext.Add (это приведет к ошибке.

Другими словами, у меня есть метод

    private void btnClockIn_Click(object sender, RoutedEventArgs e)
    {
         // I will like to add items to the observable collection in here

Это то, что я пробовал, и оно не работает:

    dynamic collection; 


private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
       // CurrentEmploye some employee
       Entities.DatabaseModel m = new Entities.DatabaseModel();
       var q = from t in m.TimeSheet                            
                join emp in m.Employees on t.idEmployee equals emp.id
                where emp.id == CurrentEmploye.id
                select new
                {
                    firstName = emp.firstName,
                    lastName = emp.lastName,
                    position = emp.position,
                    clockInDate = t.clockInDate,
                    clockOutDate = t.clockOutDate,
                };

       collection = ToObservableCollection(q); 
 }


    private void btnClockIn_Click(object sender, RoutedEventArgs e)
    {

         collection.Add(new
                {
                    firstName = "Antonio",
                    lastName = "Nam",
                    position = "Amin",
                    clockInDate = DateTime.Now,
                    clockOutDate = DateTime.Now
                });

Ответы [ 2 ]

3 голосов
/ 03 апреля 2012

Вы можете «обмануть» его, используя аналогичную «шаблонную» анонимную переменную ...
например метод кода будет что-то вроде ...

static ObservableCollection<T> CastToEnumerable<T>(this T template, object value)
{
    return (ObservableCollection<T>)value;
}

... и используйте это как-то так ...

var list = new
{
    firstName = "",
    lastName = "",
    position = "",
    clockInDate = DateTime.MinValue,
    clockOutDate = DateTime.MinValue
}.CastToEnumerable(context);
foreach (var value in list)
{ 
}

... все же рекомендуется иметь нормальный именованный класс для вашей цели.
Вы можете найти больше информации о подобной проблеме здесь ...
Приведение к анонимному типу
(Как правило, вы не можете вернуть анонимный тип - если не считать трюков, подобных этому - за этим стоит «вывод»).

1 голос
/ 03 апреля 2012

Использование анонимных типов в местах, где вы не можете использовать вывод типов, невозможно, поэтому вы не можете, например, объявить поле класса или свойство анонимного типа.Однако неочевидным было использование логического вывода типа, который позволяет обмениваться анонимными объектами между методами.

Как я уже упоминал в своем комментарии, самый простой вариант - просто использовать именованный тип;это позволит вам определить ObservableCollection<> как переменную уровня класса или типизировать ваш DataContext в другом месте вашего класса.

В зависимости от того, как часто вам нужно использовать этот код, есть второй вариантэто включает в себя тип 100 * для вашего анонимного типа.Для этого вам необходимо знать, в каждом месте, где вы хотите использовать свой анонимный тип, какие поля имеют , в каком порядке .Также требуется, чтобы каждое использование анонимного типа существовало в одной и той же сборке - это гарантирует, что компилятор объединяет анонимные типы в один базовый тип.

Если это соответствует вашим требованиям, вы можете использовать такой «трюк», как этот:

ObservableCollection<T> Cast<T>(object obj, T typedobj)
{
  return (ObservableCollection<T>)obj;
}

private void btnClockIn_Click(object sender, RoutedEventArgs e)
{
  var temp = new 
  { 
    firstName = string.Empty, 
    lastName = string.Empty, 
    position = string.Empty, 
    clockInDate = DateTime.Min, 
    clockOutDate = DateTime.Now 
  };

  var collection = Cast(lstView1.DataContext, temp);
  collection.Add(...);
}

Позвольте мне повторить, это несколько грязный «трюк», который использует неясную деталь того, как C # реализует анонимные типы.,Это не "взлом" как таковой, поскольку поведение гарантируется спецификацией, но есть серьезные ограничения на то, как далеко это работает.Если у вас есть только одна или две такие коллекции, я бы определенно хотел дать имена вашим типам.

...