[WPF] Привязка ListBox к TreeView
От: Аноним  
Дата: 03.02.11 02:25
Оценка:
Всем доброе время суток, возникла такая задача:
Есть TreeView К нему привязана коллекция элементов, которые содержат другие элементы, уровень вложенности 3,
но в дереве должно отображаться только два уровня, вот так(реализовано):


+Level1 1
|
+--Level2 1
|
+--Level2 2

+Level1 2
|
+--Level2 3



а элементы третьего уровня должны выводиться в ListBox при выборе Level2 элемента.
Вопрос собственно в том как реализовать такую привязку, или хотя-бы куда копать
Возможно стоит копать в сторону не только биндингов

Буду рад любым ссылкам, мыслям и подсказкам
Re: [WPF] Привязка ListBox к TreeView
От: андрей_к Россия  
Дата: 03.02.11 05:59
Оценка:
Добрый день.

Binding наше фсё. А так же необходимо у TreeView изменить ItemContainerStyle. Копайте в сторону HierarchicalDataTemplate.
Re[2]: [WPF] Привязка ListBox к TreeView
От: Аноним  
Дата: 03.02.11 07:22
Оценка:
Здравствуйте, андрей_к, Вы писали:

_>Добрый день.


_>Binding наше фсё. А так же необходимо у TreeView изменить ItemContainerStyle. Копайте в сторону HierarchicalDataTemplate.


Вы, похоже, не так поняли.

Смысл в том, что ListBox уже существует на форме, и показывает какую-то информацию,
но при выборе дочернего элемента в дереве, источником данных списка должен стать
набор элементов (Items), который принадлежит модели, связанной с выбранным элементом.
Принцип как в виндовом проводнике, он отображает всю иерархию папок в дереве,
однако список файлов выводится в отдельной области. И в моем случае ListBox и
есть эта отдельная область, и я как-то не догоню, как сделать это без велосипедов.
Re[3]: [WPF] Привязка ListBox к TreeView
От: HowardLovekraft  
Дата: 03.02.11 08:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Принцип как в виндовом проводнике

В качестве контекста данных TreeView и ListBox укажите одну и ту же модель. Сделайте у этой модели свойство типа SelectedObject.
Укажите ItemsSource для списка, как
<ListBox ItemsSource="{Binding SelectedObject.Items}"></ListBox>
Re[4]: [WPF] Привязка ListBox к TreeView
От: Аноним  
Дата: 04.02.11 07:19
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

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


А>>Принцип как в виндовом проводнике

HL>В качестве контекста данных TreeView и ListBox укажите одну и ту же модель. Сделайте у этой модели свойство типа SelectedObject.
HL>Укажите ItemsSource для списка, как
HL>
HL><ListBox ItemsSource="{Binding SelectedObject.Items}"></ListBox>
HL>


А можно это сделать не изменяя модель? Просто ситуация такая, что модели должны хранить исключительно несущие информацию данные. Источником привязки служит коллекция


public List<Country> SSCDataSource
{
   get
   {
       return data;
   }
}


где data

 List<Country> data = new List<Country>();


данные обновляются асинхронно следующим кодом

Storage.DataUpdated += (s, e) =>
{
    data.Clear();               
    data.AddRange(Storage.Countries);
};
Re[5]: [WPF] Привязка ListBox к TreeView
От: HowardLovekraft  
Дата: 04.02.11 10:30
Оценка: 3 (1)
Здравствуйте, Аноним, Вы писали:

А>А можно это сделать не изменяя модель?

Можно. WPF — умный:
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <TreeView ItemsSource="{Binding}" Name="myTree">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}"></TextBlock>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>

        <ListBox Grid.Column="1" ItemsSource="{Binding ElementName=myTree, Path=SelectedItem.Children}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"></TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

где наполнение контекста данных — вот такой класс:
    public class Node
    {
        public Node(String name, IEnumerable<Node> children = null)
        {
            Name = name;
            _children = children == null ? new ObservableCollection<Node>() : new ObservableCollection<Node>(children);
        }

        public String Name { get; private set; }

        private ObservableCollection<Node> _children;
        public ObservableCollection<Node> Children
        {
            get { return _children; }
        }
    }

А>Просто ситуация такая, что модели должны хранить исключительно несущие информацию данные
Я х.з., как вы достучитесь в этом случае до выбранного элемента дерева в вашей модели. Если это, конечно, нужно.
IMHO, ViewModel для этого и нужна — чтобы оборачивать в нее Model.

Кстати, если планируете изменять содержимое коллекций, то замените List<> на ObservableCollection<>.
Re[6]: [WPF] Привязка ListBox к TreeView
От: Dron247  
Дата: 09.02.11 02:23
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Кстати, если планируете изменять содержимое коллекций, то замените List<> на ObservableCollection<>.


У меня ViewModel реализует INotifyPropertyChanged, ObservableCollection<T> не могу использовать, у меня эти данные приходят асинхронно из неизвестного числа потоков, которые еще и не синхронизируются. Просто обрабатываю события из хранилища, что данные обновились, и оповещаю ui.



Кстати, возник еще вот такой вопрос, данные я, благодаря вам, привязал, а можно ли сделать, с помощью привязок, так, чтобы в ListBox, при выборе Level1 элемента попадали не Level2 элементы выбранного, а все Level3, которые есть во всех Level2, принадлежащих выбранному Level1? Или придется реализовывать это в ViewModel, или MarkupExtension'е? Не сочтите за наглость, но подобного в статьях и учебниках я не нашел

Вот картинка, для вящщей понятности:


Твой IP на моем юзербаре
Re[7]: [WPF] Привязка ListBox к TreeView
От: HowardLovekraft  
Дата: 09.02.11 09:43
Оценка: 3 (1)
Здравствуйте, Dron247, Вы писали:

D>У меня ViewModel реализует INotifyPropertyChanged

Вы определитесь все-таки, что у вас является источником данных — model или view model.
Раньше вы писали, что:

модели должны хранить исключительно несущие информацию данные

т.е. вроде как источник данных — model. Сейчас вы упоминаете некую view model, которая реализует INotifyPropertyChanged.

Если вы выставляете в качестве источника данных model, то в случае не hello-world-задачи вы получите головную боль при реализации функционала, который не нужен в model, но требуется для отображения данных. В случае, когда источником данных является view model, все проще: вы можете манипулировать данными model, которая обернута во view model, как угодно. Например, задача:

сделать, с помощью привязок, так, чтобы в ListBox, при выборе Level1 элемента попадали не Level2 элементы выбранного, а все Level3, которые есть во всех Level2, принадлежащих выбранному Level1

решается элементарно — вы делаете у view model свойство-коллекцию, содержимое которой меняется при изменении выбранного элемента. Можно ли такое сделать исключительно с помощью разметки — .

D>ObservableCollection<T> не могу использовать, у меня эти данные приходят асинхронно из неизвестного числа потоков, которые еще и не синхронизируются. Просто обрабатываю события из хранилища, что данные обновились, и оповещаю ui.

Чем асинхронность получения данных из нескольких потоков мешает использованию ObservableCollection?
List, который у вас в примере, тоже не гарантирует потокобезопаность для экземплярных членов, так что с синхронизацией все равно придется повозиться.

Имелось ввиду вот что.
Если я правильно вас понял, то сейчас, при изменении коллекции, вы генерируете PropertyChanged для свойства.
Если содержимое коллекции всегда меняется целиком, то это понятно. А если содержимое коллекции меняется частично, то, НЯП, PropertyChanged в этом случае приведет к нерациональной перерисовке всех элементов управления, участвующих в отображении коллекции, вместо того, чтобы отразить только изменения.
Re[8]: [WPF] Привязка ListBox к TreeView
От: Dron247  
Дата: 10.02.11 03:24
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Здравствуйте, Dron247, Вы писали:


D>>У меня ViewModel реализует INotifyPropertyChanged

HL>Вы определитесь все-таки, что у вас является источником данных — model или view model.
HL>Раньше вы писали, что:
HL>

HL>модели должны хранить исключительно несущие информацию данные

HL>т.е. вроде как источник данных — model. Сейчас вы упоминаете некую view model, которая реализует INotifyPropertyChanged.

HL>Если вы выставляете в качестве источника данных model, то в случае не hello-world-задачи вы получите головную боль при реализации функционала, который не нужен в model, но требуется для отображения данных. В случае, когда источником данных является view model, все проще: вы можете манипулировать данными model, которая обернута во view model, как угодно. Например, задача:

HL>

HL>сделать, с помощью привязок, так, чтобы в ListBox, при выборе Level1 элемента попадали не Level2 элементы выбранного, а все Level3, которые есть во всех Level2, принадлежащих выбранному Level1

HL>решается элементарно — вы делаете у view model свойство-коллекцию, содержимое которой меняется при изменении выбранного элемента. Можно ли такое сделать исключительно с помощью разметки — .
<lyric>
Прошу прощения за непоследовательность, код подвергся изменениям, так-что теперь можно относительно смело сказать, что источник — viewModel. Плюс многого еще просто не понимаю, новая для меня технология. Лежит на столе толстая книжка за авторством Мэтью Мак-Доналда, стоимостью почти $100 (в моем городе), и несколько пдф-ок, и все только рисовать, по сути, учат. Что-то, чуть хитрее Hello world и стандартных бизнес-решений, заставляет перелопачивать тонны буков в интернетах. А программа не бизнес-интерфейс для базы данных, и похоже первая, среди подобных, использует wpf.
</lyric>

D>>ObservableCollection<T> не могу использовать, у меня эти данные приходят асинхронно из неизвестного числа потоков, которые еще и не синхронизируются. Просто обрабатываю события из хранилища, что данные обновились, и оповещаю ui.

HL>Чем асинхронность получения данных из нескольких потоков мешает использованию ObservableCollection?
HL>List, который у вас в примере, тоже не гарантирует потокобезопаность для экземплярных членов, так что с синхронизацией все равно придется повозиться.

ObservableCollection не работало в моем случае. Сейчас уже потеряло смысл (см. ниже)

HL>Имелось ввиду вот что.

HL>Если я правильно вас понял, то сейчас, при изменении коллекции, вы генерируете PropertyChanged для свойства.
HL>Если содержимое коллекции всегда меняется целиком, то это понятно. А если содержимое коллекции меняется частично, то, НЯП, PropertyChanged в этом случае приведет к нерациональной перерисовке всех элементов управления, участвующих в отображении коллекции, вместо того, чтобы отразить только изменения.

Данные всегда меняются целиком, так как пользователь может лишь инициировать их обновление(редкая операция, плюс на время обновления дерево закрывается оверлеем), сам-же на них никак не воздействует, только получает. К тому-же данных относительно немного, и посупают они, в результате, разом несмотря на неконтролируемые пляски с потоками (данные то защищены, синхронизации нет). Смысла в частичном обновлении нет, так-же и потому, что данные могут кардинально отличаться от предыдущих.

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


Твой IP на моем юзербаре
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.