Связка нескольких контролов через DataContext
От: Аноним  
Дата: 23.04.11 15:29
Оценка:
Рассмотрим следующие варианты использования
1) textbox + datagrid , вводим текст в textbox в гриде видим отфильрованную по некоторому запросу информацию
2) datagrid + datagrid , первый датагрид инициализируется по sql запросу при выборе элемента во второй датагрид загружается информация через запрос.

Предполагается что контролы ничего не знают друг о друге.
Есть некий контроллер который знает названия контролов и у него есть доступ к DataContext и информация о пути к данным через него.

Например для случая 1)

<Grid Name="filtervalue">
  <SomeUserControlBasedOnTextbox></SomeUserControlBasedOnTextbox>
</Grid>

<Grid Name="filtereddata">
 <SomeUserControlBasedOnDataGrid></SomeUserControlBasedOnDataGrid>
</Grid>


И у контроллера есть следующие данные

1) Name= "filtervalue", DataSource = "",
2) Name = "filterddata", DataSource="select a,b,c from table where a = @param1"

и данные о связке. Т.е. чтобы грид отобразил данные у контролера есть информация :
3) SourceName = "filtervalue", SourcePath = "SomeObject.Value" , TargetName = "filtereddata", TargetPath = "SomeObjects.Filter.Param1"

Т.е. контроллер ищет контрол FindByName, затем берет значение DataContext и получает некий объект который не является наследником DependencyObject ( связанно с тем что эти объекты могут работать только в одном потоке ). Это может быть либо ObservableCollection<> либо объект наследованный от INotifyPropertyChanged.

Соответственно по п.3. находим 2 датаконтекста, берем объекты которые им назначены, получаем в результате 2 объекта не DependencyObject, для которых нет метода SetBinding, а хотелось бы использовать именно гибкость Bindingа , в том числе чтобы не изобретать велосипед для путей TargetPath, SourcePath, а использовать как принято в Bindings.



Как лучше организовать такие связи ?
Re: Связка нескольких контролов через DataContext
От: Vladek Россия Github
Дата: 23.04.11 17:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Рассмотрим следующие варианты использования

А>1) textbox + datagrid , вводим текст в textbox в гриде видим отфильрованную по некоторому запросу информацию
А>2) datagrid + datagrid , первый датагрид инициализируется по sql запросу при выборе элемента во второй датагрид загружается информация через запрос.

А>Предполагается что контролы ничего не знают друг о друге.

А>Есть некий контроллер который знает названия контролов и у него есть доступ к DataContext и информация о пути к данным через него.



А>Соответственно по п.3. находим 2 датаконтекста, берем объекты которые им назначены, получаем в результате 2 объекта не DependencyObject, для которых нет метода SetBinding, а хотелось бы использовать именно гибкость Bindingа , в том числе чтобы не изобретать велосипед для путей TargetPath, SourcePath, а использовать как принято в Bindings.




А>Как лучше организовать такие связи ?


Описанный вариант реализации никуда не годится — слишком сложный и запутанный. И это при том, что описанные два варианта использования тривиальны в реализации на WPF!

У нас есть объект, который устанавливается в качестве DataContext где-то на верхнем уровне: в Window или в UserControl. С помощью биндинга или в коде — не важно.

1) У объекта есть строковое свойство которое привязывается к TextBox с UpdateSourceTrigger=PropertyChanged. Объект при изменении этого свойства меняет фильтр у другого своего свойства типа ICollectionView (реализуемый с помощью ListCollectionView), которое привязано к DataGrid. Всё — сценарий реализован!

Схематично:
MyObject -> DataContext
string MyObject.Filter -> TextBox.Text
ICollectionView My.Object.Data (ObservableCollection<> -> ListCollectionView) -> DataGrid.ItemsSource

2) Данными по запросу заполняется коллекция ObservableCollection<>, она никуда не привязывается. Для привязки предназначена её обёртка типа ListCollectionView. У первого такого свойства мы подписываемся на событие CurrentChanged и в обработчике заполняем данными второе свойство, организованное подобным же образом. Оба свойства привязываются к DataGrid-ам, свойство DataGrid.IsSyncronizedWithCurrentItem ставим в true.

ICollectionView My.Object.Data1 (ObservableCollection<> data1 -> ListCollectionView dataView1) -> DataGrid.ItemsSource
ICollectionView My.Object.Data2 (ObservableCollection<> data2 -> ListCollectionView dataView2) -> DataGrid.ItemsSource
dataView1.CurrentChanged -> запрос данных для data2, параметр(ы) из dataView1.Current

И всё! Никто ни о ком ничего не знает, никаких ковыряний в контекстах данных, никаких костылей.
Re[2]: Связка нескольких контролов через DataContext
От: Аноним  
Дата: 23.04.11 17:31
Оценка:
V>Описанный вариант реализации никуда не годится — слишком сложный и запутанный. И это при том, что описанные два варианта использования тривиальны в реализации на WPF!

V>У нас есть объект, который устанавливается в качестве DataContext где-то на верхнем уровне: в Window или в UserControl. С помощью биндинга или в коде — не важно.


V>1) У объекта есть строковое свойство которое привязывается к TextBox с UpdateSourceTrigger=PropertyChanged. Объект при изменении этого свойства меняет фильтр у другого своего свойства типа ICollectionView (реализуемый с помощью ListCollectionView), которое привязано к DataGrid. Всё — сценарий реализован!


V>Схематично:

V>MyObject -> DataContext
V>string MyObject.Filter -> TextBox.Text
V>ICollectionView My.Object.Data (ObservableCollection<> -> ListCollectionView) -> DataGrid.ItemsSource

V>2) Данными по запросу заполняется коллекция ObservableCollection<>, она никуда не привязывается. Для привязки предназначена её обёртка типа ListCollectionView. У первого такого свойства мы подписываемся на событие CurrentChanged и в обработчике заполняем данными второе свойство, организованное подобным же образом. Оба свойства привязываются к DataGrid-ам, свойство DataGrid.IsSyncronizedWithCurrentItem ставим в true.


V>ICollectionView My.Object.Data1 (ObservableCollection<> data1 -> ListColleых для data2, параметр(ы) из dataView1.CurrentctionView dataView1) -> DataGrid.ItemsSource

V>ICollectionView My.Object.Data2 (ObservableCollection<> data2 -> ListCollectionView dataView2) -> DataGrid.ItemsSource
V>dataView1.CurrentChanged -> запрос данн

V>И всё! Никто ни о ком ничего не знает, никаких ковыряний в контекстах данных, никаких костылей.


Пока не совсем осознал ваше решение, проблема в том что изначально я не знаю будет ли там text-box и grid, а может будет textbox-combobox.
Т.е. я не могу заранее затачиваться на то какие будут связи, я должен их считать из файла конфигурации и просроить так как написано в конфигурации.
Я просто даю возможность пользователю самому выбрать какие контролы он будет использовать ( что то на подобии CMS ) и хотелось вот использовать синтаксис binding чтобы указывать как их связать.
Т.е. пользователь сам составляет композиции из контролов и устанавливает связи. Т.е. заранее готового объекта Model для его сценария нет, он должен сформироваться динамически.
Пользователь указывает что этот контрол должен брать данные из источника1 , источнику1 передать поля из контрола2,3,4.
Пользователь также может брать готовые композиции например как 1) и 2) и объединить их. Т.е. сделать вариант
3) textbox-datagrid-datagrid, работающих по 1)му и 2му сценарию одновременно.

Еще не совсем ясно как быть с фильтром, т.к. фильтр предполагает вызов callback который возвращает true/false подходит элемент или нет, а как быть при частичной загрузке данных, когда все данные из базы нельзя загрузить их там может быть очень много что не хватит ресурсов, нужно чтобы изменение свойства фильтра каждый раз инициировало запрос к бд и считывало новый блок данных.
Re[3]: Связка нескольких контролов через DataContext
От: Vladek Россия Github
Дата: 23.04.11 18:46
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Пока не совсем осознал ваше решение, проблема в том что изначально я не знаю будет ли там text-box и grid, а может будет textbox-combobox.

А>Т.е. я не могу заранее затачиваться на то какие будут связи, я должен их считать из файла конфигурации и просроить так как написано в конфигурации.
А>Я просто даю возможность пользователю самому выбрать какие контролы он будет использовать ( что то на подобии CMS ) и хотелось вот использовать синтаксис binding чтобы указывать как их связать.
А>Т.е. пользователь сам составляет композиции из контролов и устанавливает связи. Т.е. заранее готового объекта Model для его сценария нет, он должен сформироваться динамически.
А>Пользователь указывает что этот контрол должен брать данные из источника1 , источнику1 передать поля из контрола2,3,4.
А>Пользователь также может брать готовые композиции например как 1) и 2) и объединить их. Т.е. сделать вариант
А>3) textbox-datagrid-datagrid, работающих по 1)му и 2му сценарию одновременно.

Описанный подход можно приспособить и под этот сценарий, просто используете рекурсивную композицию.

А>Еще не совсем ясно как быть с фильтром, т.к. фильтр предполагает вызов callback который возвращает true/false подходит элемент или нет, а как быть при частичной загрузке данных, когда все данные из базы нельзя загрузить их там может быть очень много что не хватит ресурсов, нужно чтобы изменение свойства фильтра каждый раз инициировало запрос к бд и считывало новый блок данных.


Не вижу проблем, у ListCollectionView есть свойство Filter, не нужно ничего фильтровать вручную. Надо просто поменять фильтр, фильтроваться будут те данные, которые уже загружены — при поступлении новых данных, они тоже будут проходить через новый фильтр.
Re[4]: Связка нескольких контролов через DataContext
От: Аноним  
Дата: 23.04.11 19:22
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, Аноним, Вы писали:



А>>Пока не совсем осознал ваше решение, проблема в том что изначально я не знаю будет ли там text-box и grid, а может будет textbox-combobox.

А>>Т.е. я не могу заранее затачиваться на то какие будут связи, я должен их считать из файла конфигурации и просроить так как написано в конфигурации.
А>>Я просто даю возможность пользователю самому выбрать какие контролы он будет использовать ( что то на подобии CMS ) и хотелось вот использовать синтаксис binding чтобы указывать как их связать.
А>>Т.е. пользователь сам составляет композиции из контролов и устанавливает связи. Т.е. заранее готового объекта Model для его сценария нет, он должен сформироваться динамически.
А>>Пользователь указывает что этот контрол должен брать данные из источника1 , источнику1 передать поля из контрола2,3,4.
А>>Пользователь также может брать готовые композиции например как 1) и 2) и объединить их. Т.е. сделать вариант
А>>3) textbox-datagrid-datagrid, работающих по 1)му и 2му сценарию одновременно.

V>Описанный подход можно приспособить и под этот сценарий, просто используете рекурсивную композицию.

Спасибо, погляжу.

А>>Еще не совсем ясно как быть с фильтром, т.к. фильтр предполагает вызов callback который возвращает true/false подходит элемент или нет, а как быть при частичной загрузке данных, когда все данные из базы нельзя загрузить их там может быть очень много что не хватит ресурсов, нужно чтобы изменение свойства фильтра каждый раз инициировало запрос к бд и считывало новый блок данных.


V>Не вижу проблем, у ListCollectionView есть свойство Filter, не нужно ничего фильтровать вручную. Надо просто поменять фильтр, фильтроваться будут те данные, которые уже загружены — при поступлении новых данных, они тоже будут проходить через новый фильтр.


Допустим у нас есть 100 записей, загружаем в кеш 20 записей, а выводим на экран 10 записей. Есть ключ по которому выдается 3 результата, которые физически расположены в 1й, 50й и 100й записях. При старте кеш будет видеть только первые 20 записей и отфильтрует 1ю запись и в гриде будет выводится одна строчка, хотя должно отображаться 3.
Т.е. как только мы задали ключ должен сразу выполнится запрос к бд и вернуть новый recordset.
Re[4]: Связка нескольких контролов через DataContext
От: Аноним  
Дата: 23.04.11 19:31
Оценка:
А>>Пока не совсем осознал ваше решение, проблема в том что изначально я не знаю будет ли там text-box и grid, а может будет textbox-combobox.
А>>Т.е. я не могу заранее затачиваться на то какие будут связи, я должен их считать из файла конфигурации и просроить так как написано в конфигурации.
А>>Я просто даю возможность пользователю самому выбрать какие контролы он будет использовать ( что то на подобии CMS ) и хотелось вот использовать синтаксис binding чтобы указывать как их связать.
А>>Т.е. пользователь сам составляет композиции из контролов и устанавливает связи. Т.е. заранее готового объекта Model для его сценария нет, он должен сформироваться динамически.
А>>Пользователь указывает что этот контрол должен брать данные из источника1 , источнику1 передать поля из контрола2,3,4.
А>>Пользователь также может брать готовые композиции например как 1) и 2) и объединить их. Т.е. сделать вариант
А>>3) textbox-datagrid-datagrid, работающих по 1)му и 2му сценарию одновременно.

V>Описанный подход можно приспособить и под этот сценарий, просто используете рекурсивную композицию.


Собственно до композиции я и дошел в плане Layoutа и присвоению элементам Layout своего DataContext. В этом случае не понятно как описать Bindings.

Или предлагается сделать древовидный Model и назначить на rootовый DataContext ? Тогда не очень понятно как связывать с структурой Layout, получится опять же Binding для каждого элемента Layout на определенное динамическое свойство.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.