Как я получаю доступ к выбранным строкам в Доступе?

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

Вот старый код: (Это - общий шаблон, который я видел на всем протяжении)

class Singleton {
    static Singleton getInstance() {...}
    void addListener(Listener listener) {...}
    void removeListener(Listener listener) {...}
}

class Leaky {
    Leaky() {
        // If the singleton changes the widget we need to know so register a listener
        Singleton singleton = Singleton.getInstance();
        singleton.addListener(new Listener() {
            void handleEvent() {
                doSomething();
            }
        });
    }
    void doSomething() {...}
}

// Elsewhere
while (1) {
    Leaky leaky = new Leaky();
    // ... do stuff
    // leaky falls out of scope
}

Очевидно, это плохо. Многие Leaky создается и никогда не собирается "мусор", потому что слушатели поддерживают их.

Здесь была моя альтернатива, которая зафиксировала мою утечку памяти. Это работает, потому что я только забочусь о слушателе события, в то время как объект существует. Слушатель не должен поддерживать объект.

class Singleton {
    static Singleton getInstance() {...}
    void addListener(Listener listener) {...}
    void removeListener(Listener listener) {...}
}

class NotLeaky {
    private NotLeakyListener listener;
    NotLeaky() {
        // If the singleton changes the widget we need to know so register a listener
        Singleton singleton = Singleton.getInstance();
        listener = new NotLeakyListener(this, singleton);
        singleton.addListener(listener);
    }
    void doSomething() {...}
    protected void finalize() {
        try {
            if (listener != null)
                listener.dispose();
        } finally {
            super.finalize();
        }
    }

    private static class NotLeakyListener implements Listener {
        private WeakReference<NotLeaky> ownerRef;
        private Singleton eventer;
        NotLeakyListener(NotLeaky owner, Singleton e) {
            ownerRef = new WeakReference<NotLeaky>(owner);
            eventer = e;
        }

        void dispose() {
            if (eventer != null) {
                eventer.removeListener(this);
                eventer = null;
            }
        }

        void handleEvent() {
            NotLeaky owner = ownerRef.get();
            if (owner == null) {
                dispose();
            } else {
                owner.doSomething();
            }
        }
    }
}

// Elsewhere
while (1) {
    NotLeaky notleaky = new NotLeaky();
    // ... do stuff
    // notleaky falls out of scope
}
8
задан Gavin Miller 3 November 2009 в 21:21
поделиться

3 ответа

Вот код для этого, но здесь есть одна загвоздка.

Private Sub Command1_Click()
     Dim i As Long
     Dim RS As Recordset
     Dim F As Form

     Set F = Me.sf.Form
     Set RS = F.RecordsetClone

     If F.SelHeight = 0 Then Exit Sub

     ' Move to the first selected record.
     RS.Move F.SelTop - 1

     For i = 1 To F.SelHeight
       MsgBox RS![myfield]
       RS.MoveNext
     Next i

End Sub

Вот загвоздка: Если код добавлен к кнопке, как только пользователь нажимает эту кнопку, выбор теряется в сетке (высота будет равна нулю). Поэтому вам нужно захватить эту информацию и сохранить ее в переменной уровня модуля с помощью таймера или других событий в форме.

Вот статья, в которой подробно описывается, как обойти уловку.
http://www.mvps.org/access/forms/frm0033.htm

Уловка 2: Это только работает с непрерывным выделением. Они не могут выбрать несколько непоследовательных строк в сетке.

Обновление:
Может быть более удачное событие, чтобы отловить это, но вот рабочая реализация с использованием свойства form.timerinterval, которое я тестировал (на по крайней мере в Access 2k3, но 2k7 должен работать нормально)

Этот код входит в ПОДФОРМУ, используйте свойство, чтобы получить значение selheight в главной форме.

Public m_save_selheight As Integer

Public Property Get save_selheight() As Integer
    save_selheight = m_save_selheight
End Property

Private Sub Form_Open(Cancel As Integer)
    Me.TimerInterval = 500
End Sub

Private Sub Form_Timer()
    m_save_selheight = Me.selheight
End Sub
8
ответ дан 5 December 2019 в 07:11
поделиться

Я использовал технику, аналогичную JohnFx

. Чтобы зафиксировать высоту выделения до того, как она исчезнет, ​​я использовал событие Exit элемента управления подчиненной формы в основной форме.

Итак, в основной форме :

Private Sub MySubForm_Exit(Cancel As Integer)

  With MySubForm.Form
    m_SelNumRecs = .SelHeight
    m_SelTopRec = .SelTop
    m_CurrentRec = .CurrentRecord
  End With

End Sub
9
ответ дан 5 December 2019 в 07:11
поделиться

Я пробовал делать что-то подобное раньше, но у меня никогда не получалось использовать метод, который требовал, чтобы пользователь выбирал несколько строк в том же стиле, что и диалоговое окно Windows File (нажатие Ctrl, Shift и т. Д.)

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

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

Даже в Access мне иногда легче работать с таблицами и запросами напрямую, чем пытаться использовать встроенные инструменты в формах Access. Иногда встроенные инструменты не делают именно то, что вам нужно.

2
ответ дан 5 December 2019 в 07:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: