Модераторы: gambit, Kefir, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C# WPF MVVM Editable Combobox in DataGrid 
:(
    Опции темы
Cuguyc
Дата 22.9.2014, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 22.9.2014

Репутация: нет
Всего: нет



Добрый день.
Никак не получается сделать редактируемый Combobox в DataGrid'е. Точнее заставить его работать правильно.
Задача:
Создать редактируемый Combobox в DataGrid.
При нажатии должен открываться выпадающий список.
При вводе текста нужно чтобы выпадающий список сокращался в зависимости от введенных значений.
Что бы была возможность как выбирать из выпадающего списка так и вводить значение полностью.

И так, что я сделал и что у меня не работает:

Код XAML представления:
Выделить всёРазвернуть кодРазметка XML
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
<UserControl.Resources>
        <Style TargetType="{x:Type ComboBox}">
            <Setter Property="StaysOpenOnEdit" Value="True"/>
        </Style>
</UserControl.Resources>
                    <DataGridTemplateColumn MinWidth="100" Header="Валюта" >
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                        <ComboBox   ItemsSource="{Binding Path=Currences}"
                                    SelectedItem="{Binding DataContext.SelectedCurrency, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
                                    IsTextSearchEnabled="False"
                                    IsEditable="True"
                                    DisplayMemberPath="CurrencyVal"
                                    Text="{Binding DataContext.Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}">
                                   
                                    <ComboBox.Style>
                                        <Style TargetType="ComboBox">
                                            <Style.Triggers>
                                                <MultiTrigger>
                                                    <MultiTrigger.Conditions>
                                                        <Condition Property="IsKeyboardFocusWithin" Value="true"/>
                                                    </MultiTrigger.Conditions>
                                                    <MultiTrigger.Setters>
                                                        <Setter Property="IsDropDownOpen" Value="True" ></Setter>
                                                    </MultiTrigger.Setters>
                                                </MultiTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </ComboBox.Style>                                    
                                </ComboBox>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>



MultiTrigger - помогает открывать выпадающий список по фокусу на комбо бокс
В ресурсах соответственно не дает выпадающему списку закрыться при вводе
SelectedItem привязка к коллекции
Text привязка к свойству

Код ViewModel


Выделить всёРазвернуть кодкод C#
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
//В конструкторе
var notes = OfficialNoteMain.OfficialNote;
            if (notes == null)
            {
                OfficialNoteCollection = new ObservableCollection<OfficialNote> OfficialNote };
            }
            else
            {
                if (!notes.Any())
                {
                    notes.Add(OfficialNote);
                }
                OfficialNoteCollection = new ObservableCollection<OfficialNote>();
                foreach (var item in notes)
                {
                    item.Currency = SelectedCurrency;
                    item.Currences = Currences;
                    OfficialNoteCollection.Add(item);
                }
            }
//Конец конструктора
private ObservableCollection<Currency> _currencies;
        public ObservableCollection<Currency> Currences // Коллекция валют 
        {
            get return _currencies ?? (_currencies = new ObservableCollection<Currency>(_repository.GetAllItems<Currency>()))}
        }
public string Text 
        {
            get
            {
                if (SelectedCurrency != null)
                    return SelectedCurrency.CurrencyVal;
                else
                {
                    return null;
                }
            }
            set
            {
                if (!string.IsNullOrEmpty(value))
                {
                    Currences.Clear();
                    foreach (var item in _repository.GetFirstItemsPredicate<Currency>(20).Where(x => x.CurrencyVal != null).Where(z => z.CurrencyVal.ToLower().Contains(value.ToLower())))
                        Currences.Add(item);
                    if (_repository.GetAllItems<Currency>().FirstOrDefault(x => x.CurrencyVal.Contains(value)) != null)
                        SelectedCurrency = _repository.GetAllItems<Currency>().First(x => x.CurrencyVal.Contains(value));
                }
            } 
        }
        private Currency _currency;
        public Currency SelectedCurrency
        {
            get
            {
                return _currency;
            }
            set
            {
                _currency = value;
            }
        }



В моделе только:

Выделить всёкод C#
1:
public ObservableCollection<Currency> Currences get; set; }



Весь код не выкладывал, там много лишнего, постарался выложить по максимуму.

Проблема в том, что данные не записываются в бд.
Если забиндить только SelectedItem, то в принципе работает но если вводишь текст то естественно не сохраняется. Сохраняется только если выбрал из выпадающего списка. Ну и выпадающий список конечно же не сокращается.

В свойства по сути заходит, так что проблема не в привязке.
коллекция сокращается при вводе, выпадающий список открывается, это работает.
Сохранение в базу тоже работает, тут скорее дело в той ереси, что я написал внутри свойств SelectedCurrency и Text.
Для работы с бд использую LinqToSQL, класс модели, это партикл класс таблицы грубо говоря.

Пожалуйста помогите разобраться, может кто сталкивался с проблемой?

P.S. Прошу сильно палками не бейте сам знаю, что много "гомнокода" написал.

PM MAIL   Вверх
Ilya81
Дата 23.9.2014, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 105
Регистрация: 18.4.2014
Где: ЛО, Всеволожский р-н

Репутация: 1
Всего: 4



Что ComboBox всё ж открывается, даже интересно, обычно я его помещаю в CellEditingTemplate, а не в CellTemplate. Но если setter свойства вызывается, то WPF не связан с сохранением в БД (ибо WPF только вызывает setter указанного в binding свойства). Обновление ObservableCollection точно не приведёт к записи в БД, для этого нужно вызвать методы Attach и Add у DbSet, а потом SaveChanges у DbContext. Запись в БД рекомендую делать не в UI-потоке.
PM MAIL ICQ Skype   Вверх
Cuguyc
Дата 23.9.2014, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 22.9.2014

Репутация: нет
Всего: нет



Я наверное не правильно написал, в базу всё записывается, но у меня путаница с привязкой текста и  selectedItem'a.

Вот очередная попытка сделать чтоб всё работало:

код модели:
        
Выделить всёРазвернуть кодкод C#
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
        public List<Currency> AllCurrencies get; set; }
        public ObservableCollection<Currency> Currences get; set; }
private string _text;
        public string Text
        {
            get return _text; }
            set
            {
                //if (_text == null) return;
                if (Text != null)
                    SelectedCur = null;
                if (SelectedCur == null)
                {
                    _text = value;
                    Currences.Clear();
                    int i = 0;
                    foreach (var cur in AllCurrencies.Where(x => x.CurrencyVal.Contains(_text)))
                    {
                        if(i==0)
                            Currences.Add(cur);
                    }
                    var concreteCur = Currences.SingleOrDefault(x => x.CurrencyVal == _text);
                    if (concreteCur != null)
                    {
                        SelectedCur = concreteCur;
                    }
                    if (PropertyChanged != null)
                    {
                        OnPropertyChanged("Text");
                    }
                }
                else
                {
                    _text = SelectedCur.CurrencyVal;
                }
            }
        }
        private Currency _selectedCur;
        public Currency SelectedCur
        {
            get return _selectedCur; }
            set
            {
                _selectedCur = value;
                //if (value != null)
                //    Text = value.CurrencyVal;
            }
        }


Код представления:
Выделить всёРазвернуть кодРазметка XML
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
<DataGridTemplateColumn MinWidth="100" Header="Валюта" >
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                            <ComboBox   ItemsSource="{Binding Path=Currences}"
                                        IsTextSearchEnabled="False" 
                                        SelectedItem="{Binding Path=SelectedCur, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                        IsEditable="True"
                                        DisplayMemberPath="CurrencyVal"
                                                        
                                        Text="{Binding Path=Text, Mode=TwoWay,
                                  UpdateSourceTrigger=PropertyChanged}"
                                        >
                                   
                                        <ComboBox.Style>
                                            <Style TargetType="ComboBox">
                                                <Style.Triggers>
                                                    <MultiTrigger>
                                                        <MultiTrigger.Conditions>
                                                            <Condition Property="IsKeyboardFocusWithin" Value="true"/>
                                                        </MultiTrigger.Conditions>
                                                        <MultiTrigger.Setters>
                                                            <Setter Property="IsDropDownOpen" Value="True" ></Setter>
                                                        </MultiTrigger.Setters>
                                                    </MultiTrigger>
                                                </Style.Triggers>
                                            </Style>
                                        </ComboBox.Style>
                                    
                                    </ComboBox>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>


Я уже что только не пробую...
Текст биндится и заходит в поле.
Выбранный элемент тоже биндится и заходит в поле
и список тоже
но всё вместе отрабатывает не правильно
Тут я явно косячу в геттерах и сеттерах текста и выбранного элемента, я путаюсь и не понимаю как сделать правильно. Мне надо, чтоб и вводимый текст мог добавляться и выбранный элемент, при всём при этом что бы выбранный элемент нормально отображался. 
Бывает, что я пишу текст, не дописал, выбираю из списка и всё пропадает к примеру и куча таких мелких косяков и в итоге не корректно работает. 
В базу добавление нормально отрабатывает, у меня есть проверочная текстовая колонка, там всё норм, комбо бокс тоже добавляется по сути...

Добавлено через 3 минуты и 51 секунду
Вот кажется, ну задача не из сверхфантастических, просто в таблице должен быть редактируемый комбо бокс с сокращающимся при вводе выпадающим списком, что бы можно было и в ручную полностью записать значение и выбрать... Но не получается как-то... Конечно я не гуру wpf программирования, но я думал что подобная задача не должна составить проблем, однако видимо ошибся.
PM MAIL   Вверх
Ilya81
Дата 24.9.2014, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 105
Регистрация: 18.4.2014
Где: ЛО, Всеволожский р-н

Репутация: 1
Всего: 4



Стало понятнее, о чём речь. Попробуйте у ComboBox задать значение SelectedValuePath равным "CurrencyVal" (в XAML'е) и поставить binding для свойства SelectedValue (вместо SelectedItem) на строковое свойство.
PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | WPF и Silverlight | Следующая тема »


 




[ Время генерации скрипта: 0.1083 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.