Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка Windows Forms > Биндинг в WPF


Автор: Ghost_XIII 16.1.2008, 15:14
Всем доброго времени суток smile 
Помогите решить вот такую вот проблему:

Есть 2 класса
Код

    public class DataItem : INotifyPropertyChanged
    {
        public uint ID
        {
        }

        public string Name
        {
        }

        public static bool operator ==(DataItem item1, DataItem item2)
        {
            return item1.Equals(item2);
        }

        public static bool operator !=(DataItem item1, DataItem item2)
        {
            return !item1.Equals(item2);
        }

        public override bool Equals(object obj)
        {
            DataItem temp = obj as DataItem;
            if (temp == null) return false;
            if (this.name == temp.name) return true;
            else return false;
        }
    }

    public class DataItemCollection : ObservableCollection<DataItem>
    {
        public DataItemCollection()
            : base()
        {
        }
    }

(чтобы съэкономить место я почти всё из них повыризал, оставив тока самое основное)

и ресурс окна
Код

    <Window.Resources>
        <l:DataItemCollection x:Key="Items" x:Name="Items"/>
    </Window.Resources>


Я этот ресурс биндю к ListBox
Код

        <ListBox Name="ViewBox" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="7" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                 ItemsSource="{DynamicResource ResourceKey=Items}" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True"/>


и назначаю обработчик нажатия кнопки
Код

        private void AddBtn_Click(object sender, RoutedEventArgs e)
        {
            uint count = 0;
            DataItemCollection items = this.FindResource("Items") as DataItemCollection;
            count = (uint)items.Count;
            count++;
            DataItem newItem = new DataItem(count, string.Format("Item {0}", count));
            items.Add(newItem);
        }


Проблема заключается в следующем: после первого нажатия к списку нормально добавляестя повый элемент, а вот во время попытки добавить второй элемент почему то происходит вызов перегруженного оператора "==" при этом item1 - это первый элемент в списке (и пока единственный), а item2 вобще null. Самое интересное, что сравнение происходит в цикле. первый раз сравнивает item1 и null, а потом и вообще  null с null. 
В результате получается, что после второго нажатия на кнопку, прога выдаёт либо, что объект равен null, либо, если делать проверку на нулы - переполнение стека.

Всё нормально работает если:
1 - не связывать ListBox с ресурсом
2 - не перегружать оператор ==

Помогите плиз, а то я уже себе всю голову сломал smile 

Автор: tol05 16.1.2008, 16:22
я в WPF не гуру, а для того, чтобы проимитировать твою ситуацию нужно дебагать проект. Проект ты не выложил, писать его, стало быть, нужно нам самим...

Но по своему опыту работы с устаревшими технологиями  smile  (FW 2.0 я имею в виду) могу сказать следующее:
Цитата(Ghost_XIII @  16.1.2008,  14:14 Найти цитируемый пост)
Я этот ресурс биндю к ListBox
т.е. контрол связан с источником данных и отображает часть его содержимого. Ты меняешь содержимое контрола, а содержимое источника его данных - не меняешь. Это плохо. Контрол пытается отображать то, чего нет в его источнике данных.

Одним словом, попробуй в обработчике клика добавлять item не в сам листбокс, а в ресурс, к которому биндится листбокс.

P.S. ну а почему вызывается оператор "==" ?
Просто внутри ф-ции Add вызывается ф-ция

Цитата

internal static void ChangeValue(DataItemCollection col, DataItem oldValue, DataItem newValue)
{
    if (oldValue != newValue)
    {
        if ((newValue != null) && (newValue.parent != null))
        {
            throw new InvalidOperationException(SR.DataItem_IsAlreadyUsedForAnotherObject);
        }
        if (oldValue != null)
        {
            oldValue.MoveTo(null, null);
        }
        if (newValue != null)
        {
            newValue.MoveTo(col, col.parent.Container);
        }
    }
}

вот и все. Юзай рефлектор.

Автор: Ghost_XIII 16.1.2008, 18:14
Собсна ресурс я и меняю
Цитата

            DataItemCollection items = this.FindResource("Items") as DataItemCollection;
            items.Add(newItem);


Меня не удивило, если бы оно (==) один раз вызывалось, но когда оно попадает в какой то непонятный цикл?

Прикладываю проект

Автор: Kefir 18.1.2008, 10:21
у тебя плохо перегружен ==. там стоит item1.Equals(item2). Просто поправь так, чтобы учитывался вариант когда нули. Ну там if (item1 == null) return false; или что тебе там надо. А то оно бедное пытается у нуля вызвать ф-цию Equals. А це кидает ошибку что мол - я нуль и ни черта не умею. должно заработать.

Автор: Ghost_XIII 18.1.2008, 10:59
Сразу же возникает вопрос - каково она вообще у нула вызывает == ?! но это наверное недостаток в моём образовании.

Ставил уже. Проверял все возможные нулы. Итог - стек оверфлоу. Так как она как зашла один раз в == так там и крутится пока не загнётся

Автор: Jlekc 18.1.2008, 12:07
коректнее написать:
Код

public override bool Equals(object obj)
        {
            DataItem temp = obj as DataItem;
            if (object.Equals(temp, null)) return false;  // if (temp == null) return false;
            if (this.name == temp.name) return true;
            else return false;
        }


Автор: Ghost_XIII 18.1.2008, 12:29
Jlekc, Спасибо. Помогло.

Хотел спросить в чём разница между этими двумя строчками, но пока писал вопрос сам понял smile 

Я то думал, что она при добавлении нового элемента вызывает ==, а она оказывается вызывает Equals, что вполне естественно

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)