Проблема с обновлением элемента управления ListBox в WPF

У меня есть приложение, которое должно отслеживать 211 стержней, и каждые 5 секунд оно будет обновлять 2 элемента управления ListBox, каждый из которых содержит либо вставленные стержни, либо удаленные. Когда я вручную использую кнопку для вставки/удаления стержней, код выполняется отлично, и списки обновляются правильно. Когда я использую глобальную кнопку, которая вставляет все 211, один из элементов управления ListBox перестает работать должным образом.

Код для обновления ListBox

bool IClear = true, RClear = true;
        for (int foo = 0; foo < Rods.Count; foo++)
        {
            if (Rods[foo].State == RodState.Inserted)
            {
                UpdateRodList update = new UpdateRodList(UpdateIRodUI);
                if (IClear)
                {
                    InsertedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, true);
                    IClear = false;
                }
                else
                {
                    InsertedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, false);
                }
            }
            if (Rods[foo].State == RodState.Removed)
            {
                UpdateRodList update = new UpdateRodList(UpdateRRodUI);
                if (RClear)
                {
                    RemovedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, true);
                    RClear = false;
                }
                else
                {
                    RemovedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, false);
                }
            }
        }

Код кнопки вставки (удалить аналогично)

Int32[] RodsID = null;
        bool bParsed = false;
        if (RemovingRods_.Text.Contains("*"))
        {
            RodsID = new Int32[211];
            for (int i = 0; i < 211; i++)
            {
                RodsID[i] = i;
            }
            RemovingRods_.Text = "";
            bParsed = true;
        }
        if (RemovingRods_.Text.Contains("-"))
        {
            string stext = RemovingRods_.Text;
            Int32 a = Int32.Parse(RemovingRods_.Text.Substring(0, RemovingRods_.Text.IndexOf("-")));
            Int32 b = Int32.Parse(RemovingRods_.Text.Substring(RemovingRods_.Text.IndexOf("-") + 1));
            RodsID = new Int32[b - a];
            for (int i = 0; i < b - a; i++)
            {
                RodsID[i] = i + a;
            }
            RemovingRods_.Text = "";
            bParsed = true;
        }
        if (!bParsed)
        {
            string[] RodsID_;
            char[] split = { ' ' };
            RodsID_ = RemovingRods_.Text.Split(split);
            RemovingRods_.Text = "";
            RodsID = new Int32[RodsID_.Length];
            for (int i = 0; i < RodsID_.Length; i++)
            {
                RodsID[i] = Int32.Parse(RodsID_[i]);
            }
        }
        foreach (int numb in RodsID)
        {
            if (Rods[numb].Type == "Control Rod")
            {
                ControlRod Rod = new ControlRod();
                Rod.Number = numb;
                Rod.RodState = RodState.Changing;
                RemovingCRods.Add(Rod);
            }
            if (Rods[numb].Type == "Shortened Control Rod")
            {
                ShortenedControlRod Rod = new ShortenedControlRod();
                Rod.Number = numb;
                Rod.RodState = RodState.Changing;
                RemovingSRods.Add(Rod);
            }
            if (Rods[numb].Type == "Automated Control Rod")
            {
                // Automated Rods -- NO MANUAL CONTROL
            }
        }

И глобальный код кнопки

try
        {
            Int32[] RodsID = null;
            string text = "0-211";
            RodsID = new Int32[211];
            for (int i = 0; i < 211; i++)
            {
                RodsID[i] = i;
            }
            foreach (int numb in RodsID)
            {
                if (Rods[numb].Type == "Control Rod")
                {
                    ControlRod Rod = new ControlRod();
                    Rod.Number = numb;
                    Rod.RodState = RodState.Changing;
                    InsertingCRods.Add(Rod);
                }
                if (Rods[numb].Type == "Shortened Control Rod")
                {
                    ShortenedControlRod Rod = new ShortenedControlRod();
                    Rod.Number = numb;
                    Rod.RodState = RodState.Changing;
                    InsertingSRods.Add(Rod);
                }
                if (Rods[numb].Type == "Automated Control Rod")
                {
                    AutomatedControlRod Rod = new AutomatedControlRod();
                    Rod.Number = numb;
                    Rod.RodState = RodState.Changing;
                    InsertingARods.Add(Rod);
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

Что происходит, когда я нажимаю глобальную, в списке удаленных стержней будут все стержни, как и должно быть, а в списке вставленных стержней будут содержаться стержни, которые были вставлены до того, как я нажал кнопку. Как будто когда я нажимаю эту кнопку, этот элемент управления не обновляется. P.S. Если я удаляю стержни вручную с помощью кнопки или вставляю, все работает отлично.

Что касается кода, запрошенного Марко:

 private void UpdateIRodUI(Int32 foo, Boolean clear)
    {
        if (clear)
        {
            InsertedRods.Items.Clear();
        }
        InsertedRods.Items.Add(Rods[foo].Number + " : " + Rods[foo].Type + " (" + foo.ToString() + ")");
    }

    private void UpdateRRodUI(Int32 foo, Boolean clear)
    {
        if (clear)
        {
            RemovedRods.Items.Clear();
        }
        RemovedRods.Items.Add(Rods[foo].Number + " : " + Rods[foo].Type + " (" + foo.ToString() + ")");
    }

Обновление: я поместил код обновления ListBox в отдельную функцию и последовал совету Марко, а также добавил функцию InsertRods. Теперь все работает нормально, но кажется, что после того, как я нажму «аварийную» кнопку, ListBox InsertedRods обновляется и работает нормально, но RemovedRods просто перестает обновляться, если только я не сделаю это вручную (он должен обновляться каждые 5 секунд через событие Tick). Я даже пробовал вставлять все стержни, обновлять ListBoxes и очищать «неисправный» ListBox, но все равно ничего, тот же результат.


person Andrew    schedule 09.10.2010    source источник


Ответы (1)


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

1) Вы разместили свой код для обновления ListBox, но из двух других фрагментов кода неясно, где вы вызываете метод обновления ListBox?

2) Код, который вы разместили для «кнопки вставки», больше похож на код «кнопки удаления» из-за Removing_Rods.Add()... Но почему вы дублируете свой код кнопки вставки/удаления в глобальный код кнопки ? Почему бы не использовать метод вставки, который вызывается как кнопкой вставки, так и глобальной (вставить) кнопкой? И то же самое для удаления. Если вам нужно немного изменить код в зависимости от того, является ли вызывающий объект кнопкой вставки или глобальной кнопкой, вы можете передать переменную и проверить ее внутри метода вставки.

3) Пробовали ли вы отлаживать свой код? Например, вызывается ли метод обновления списка при выполнении кода глобальной кнопки...

person Marko    schedule 09.10.2010
comment
2) Да, мой плохой код предназначен для удаления стержней. Я собираюсь попробовать написать это в функции, спасибо за совет. Что касается 3), у меня нет, но я предполагаю, что он частично работает, так как один ListBox обновляется, а другой - нет. - person Andrew; 10.10.2010
comment
Из-за 1) невозможно сказать, почему ваш список не обновляется. Предоставленный вами код никогда не вызывает обновление списка, возможно, именно поэтому у вас возникла проблема. Из-за дублирующегося кода в глобальной кнопке может отсутствовать вызов обновления списка. Что касается 3), это первое, что должен сделать любой программист, прежде чем даже думать о Google или задавать вопрос о stackoverflow. В фильме Undersiege 2 было прекрасное замечание - Успенская - мать всех пиздецов!. - person Marko; 10.10.2010
comment
Ах, только что заметил, что вы немного обновили свой вопрос. Предположим, вы добавили метод UpdateRRodUI(), и я предполагаю, что RemovedRods является фактическим полем со списком (мой совет — ставить перед всеми элементами управления пользовательского интерфейса их фактические типы, например, listBoxRemovedRods), но я все еще не вижу никаких вызовов, сделано для UpdateRRodUI(). Таким образом, лучший совет, который я могу вам дать, это отладить ваш код, установить точку останова в UpdateRRodUI() и посмотреть, сработает ли она вообще. Если нет, то установите точку останова в том фрагменте кода, который обрабатывает стержни, и выполните его построчно, чтобы увидеть, почему UpdateRRodUI никогда не вызывается... - person Marko; 10.10.2010