Ребят, хитрый вопрос по поведению приложения: есть "морда к базе". Перед работой, разумеется, делается логин в базу (юзер вводит пароль). Только после этого становятся доступными данные таблиц.
НО(!) на главной форме есть комбобокс, куда засасываются справочные данные, используя сам же XAML:
Проблема в том, что как только главная форма инициализирована (но до логина), она пытается заполнить комбобокс и лезет в App.PersonStatus , который разумеется требует уже авторизованное соединение с базой, а оно у меня ещё null.
Решение №1 — тупо загружать комбобокс из кода. Что совсем не интересно и не эстетично.
Решение №2 МОГЛО БЫ сработать, если бы у комбобокса была отложенная загрузка. Что обидно: где НЕ надо, отважные индусы вкорячили в WPF "отложенную загрузку" всего и вся, но вот для ItemsSource её почему-то нет! (ведь я ещё не раскрывал ComboBox, зачем УЖЕ сосать туда данные?)
Решение №3 — открывать отдельное read-only соединение к базе (ещё перед инитом формы) и сосать справочные данные оттуда. Но это костыль и самое последнее, что хочется делать.
Есть какие-то ещё варианты, как задержать загрузку ItemsSource?
Здравствуйте, Kolesiki, Вы писали:
K>Решение №3 — открывать отдельное read-only соединение к базе (ещё перед инитом формы) и сосать справочные данные оттуда. Но это костыль и самое последнее, что хочется делать. K>Есть какие-то ещё варианты, как задержать загрузку ItemsSource?
Нормальный вариант, в чем проблема прочитать данные из таблицы? Ну придется заморочится с правами
доступа для этой и других таблиц разве что.
K><ComboBox ItemsSource="{Binding PersonStatus, Source={x:Static local:App.Current}}" /> K>Есть какие-то ещё варианты, как задержать загрузку ItemsSource?
Оставить при старте этот PersonStatus пустым, затем когда появится соединение с базой — загрузить в него данные и вызвать ему PropertyChanged.
Здравствуйте, Kolesiki, Вы писали:
K>Есть какие-то ещё варианты, как задержать загрузку ItemsSource?
Решение № 4: Сделать нормальную ViewModel для окна, а не биндить к классу приложения.
В этой ViewModel уже изначально оставить коллекцию пустой, а после аутентификации подгрузить данные в неё. Коллекцию сделать ObservableCollection, чтобы WPF подхватывал её изменения автоматом.
Здравствуйте, Sharov, Вы писали:
S>Нормальный вариант, в чем проблема прочитать данные из таблицы? Ну придется заморочится с правами доступа для этой и других таблиц разве что.
Вот это. Потому что:
1. Никто не Ванга и я не знаю, что мы будем использовать завтра. Может, это будут REST-сервисы, может Postgres, может ещё какая хрень. Завязываться на возможность "readonly соединения" не хочется.
2. Это лишний коннекшн, за которым тоже придётся следить, вовремя менять conn.string и т.п.
3. Лишний гемор при сетапе. Особенно для "людей в поле" (слабоквалифицированные технари, которые максимум могут запустить setup.exe).
Ну то есть я не отвергаю его категорически, но показал как не самый лучший вариант.
Здравствуйте, alexsmirnoff, Вы писали:
K>>Решение №1 — тупо загружать комбобокс из кода. Что совсем не интересно и не эстетично.
A>Почему?
Потому что декларативно это удобнее: объявлен контрол и ВСЕ сопутствующие ему настройки, т.е. сам C# код — чистый.
K>>Есть какие-то ещё варианты, как задержать загрузку ItemsSource?
A>Дак тут получается не "задержать", а "держать, пока не выполнено условие". A>Разве нельзя его создать задизабленным, а после логина раздизаблить?
Пробовал — НЕ ПОМОГАЕТ! Я даже больше скажу — этот комбобокс лежит на задизэйбленом табе, который даже не выбран!! Т.е. у мелкомягких макак было как минимум ТРИ препятствия-условия, при которых ну совсем не надо лезть за данными! ППЦ....
Здравствуйте, Osaka, Вы писали:
O>Оставить при старте этот PersonStatus пустым, затем когда появится соединение с базой — загрузить в него данные и вызвать ему PropertyChanged.
Это равносильно тупо загрузить его в коде после логина. Не очень хочется загружать код.
Здравствуйте, karbofos42, Вы писали:
K>Решение № 4: Сделать нормальную ViewModel для окна, а не биндить к классу приложения.
Для сферического мира хелловорлдов — да, это "нормальную ViewModel". Но не везде и не всегда удобно городить отдельный почти дублирующий слой VM-классов. Вообще, на будущее: MVVM — далеко не идеальная модель, лучше не бросаться замусоривать проект "идеологиями".
K>В этой ViewModel уже изначально оставить коллекцию пустой, а после аутентификации подгрузить данные в неё. Коллекцию сделать ObservableCollection, чтобы WPF подхватывал её изменения автоматом.
Это практически ничем не отличается от того, чтобы тупо загрузить данные после логина. Было. Не хочу.
В целом, это как бы и не страшная проблема — так или иначе я догружу. Но имея декларативный XAML, хочется побольше взвалить на него. Просто бывает, что не знаешь каких-то тонкостей, где одним атрибутом можно решить все проблемы.
Здравствуйте, Kolesiki, Вы писали:
K>Вот это. Потому что: K>1. Никто не Ванга и я не знаю, что мы будем использовать завтра. Может, это будут REST-сервисы, может Postgres, может ещё какая хрень. Завязываться на возможность "readonly соединения" не хочется.
Так это все на стороне бд, настройки и т.д. Разве что бд поменяется, но это довольно редкое явление.
K>2. Это лишний коннекшн, за которым тоже придётся следить, вовремя менять conn.string и т.п.
Вот тут не уверен(не знаю). Скорее всего понадобиться отдельный логин и пароль для такого пользователя.
А cs будет таже.
K>3. Лишний гемор при сетапе. Особенно для "людей в поле" (слабоквалифицированные технари, которые максимум могут запустить setup.exe).
Да, возможно. Ну будет же скрипт, который будет создавать бд. Вот туда и добавить эту логика со спец. пользователем
с правами только на чтение таблицы.
Здравствуйте, Kolesiki, Вы писали:
K>Здравствуйте, karbofos42, Вы писали:
K>>Решение № 4: Сделать нормальную ViewModel для окна, а не биндить к классу приложения.
K>Для сферического мира хелловорлдов — да, это "нормальную ViewModel". Но не везде и не всегда удобно городить отдельный почти дублирующий слой VM-классов. Вообще, на будущее: MVVM — далеко не идеальная модель, лучше не бросаться замусоривать проект "идеологиями".
Как раз для хелловорлда можно забить и не дублировать.
"Дублирующий" слой больше контроля в итоге даст и поддержка проще будет.
А биндинг — это не замусоривание?
А в класс Application коллекции из БД грузить — это нормально?
K>>В этой ViewModel уже изначально оставить коллекцию пустой, а после аутентификации подгрузить данные в неё. Коллекцию сделать ObservableCollection, чтобы WPF подхватывал её изменения автоматом.
K>Это практически ничем не отличается от того, чтобы тупо загрузить данные после логина. Было. Не хочу.
Суть была в VM и намёк на то, что биндить к свойству Application — сомнительная практика.
Так-то можно завести две разные VM — для неавторизованного состояния и для авторизованного.
Либо селектором выбирать разные шаблоны в зависимости от состояния.
Запустилась программа — в окне показывается, что данных нет, нужно пройти аутентификацию.
Залогинились — теперь уже в окне все данные, которые подгрузились из БД.
VM будет создаваться после аутентификации, так что доступ к БД уже будет и только в этот момент начнут запрашиваться данные и т.п.
K>В целом, это как бы и не страшная проблема — так или иначе я догружу. Но имея декларативный XAML, хочется побольше взвалить на него. Просто бывает, что не знаешь каких-то тонкостей, где одним атрибутом можно решить все проблемы.
Этот самый XAML завязан на MVVM и биндинги все эти нормально работать будут только при условии реализации конкретных интерфейсов и т.п.
Как раз, либо это остаётся на "дублирующем слое" VM и не перемешивается с моделью и "идеология" не замусоривает проект. Либо модель будет допиливаться под View и тогда всё будет прибито гвоздями к WPF и т.п.
K>Есть какие-то ещё варианты, как задержать загрузку ItemsSource?
2 варианта: 1. App должен реализоовать INotifyPropertyChanged, когда залогинились делаем так, чтобы PersonStatus возвращал заполненную коллекцию и шлём PropertyChanged на свойство PersonStatus
2. PersonStatus должен возвращать ObservableCollection (INotifyCollectionChanged), когда залогинились заполняем эту коллекцию
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Здравствуйте, Kolesiki, Вы писали:
K>Ребят, хитрый вопрос по поведению приложения: есть "морда к базе". Перед работой, разумеется, делается логин в базу (юзер вводит пароль). Только после этого становятся доступными данные таблиц. K>НО(!) на главной форме есть комбобокс, куда засасываются справочные данные, используя сам же XAML:
K>
Биндинг должен работать сразу, просто источник данных сначала будет выдавать пустой список, а когда он станет готов — выдаст полный список. В WPF для этого всё есть: ListCollectionView в связке с ObservableCollection.
Лучше всего завести модель вида для главной формы, ей добавить свойство с этим списком — заполнить список данными, когда он будет готов. WPF подхватит всё это автоматом.