Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.85/34: Рейтинг темы: голосов - 34, средняя оценка - 4.85
1 / 1 / 2
Регистрация: 18.12.2013
Сообщений: 239
1

Динамическое заполнение ListView

07.02.2020, 12:50. Показов 6103. Ответов 15
Метки нет (Все метки)

Недавно начал разбираться с WPF? Сразу извиняюсь за вопрос.

В главное окно вложено другое, в котором пустой ListView.
В коде вложенного окна и в основном есть своя кнопка, которая должна заполнить ListView данными.
Понимаю примерно почему во вложенном окне работает, а из основного нет, но не могу понять как исправить.
Буду так же благодарен, если кто нибудь предложит пример другой реализации. Задача состояла заполнить ListView не указывая наименования столбцов в в разметке XAML.

MainWindow.xaml

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Window x:Class="ListViewTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ListViewTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen" >
 
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Click="Button_Click" Content="Загрузить из MainWindow" Background="#FFEEEE24"/>
 
        <local:MyList Grid.Row="1" x:Name="DataTable"/>
        
    </Grid>
</Window>
MainWindow.xaml.cs

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Windows;
 
namespace ListViewTest
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MyList milist = new MyList();
            milist.LoadMyList();
        }
    }
}
MyList.xaml

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<UserControl x:Class="ListViewTest.MyList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ListView_column"
             mc:Ignorable="d" 
             d:DesignHeight="500" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MyList" Background="#FF2EEE0F" Click="Button_Click"/>
        <ListView MouseDoubleClick="ListView_MouseDoubleClick" Name="DataList" Grid.Row="1" ItemsSource="{Binding}" Background="#FFE4F3EF"/>
    </Grid>
</UserControl>
MyList.xaml.cs

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
67
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Data;
 
namespace ListViewTest
{
    /// <summary>
    /// Логика взаимодействия для UserControl1.xaml
    /// </summary>
    public partial class MyList : UserControl
    {
        public MyList()
        {
            InitializeComponent();
            DataList.DataContext = db;
        }
 
        DataTable db = new DataTable();
 
        public void LoadMyList()
        {
            db.Rows.Clear();
            db.Columns.Clear();
            db.Columns.Add(new DataColumn("Имя"));
            db.Columns.Add(new DataColumn("Фамилия"));
 
            db.Rows.Add(db.NewRow());
            db.Rows[0]["Имя"] = "Иван";
            db.Rows[0]["Фамилия"] = "Иванов";
 
            db.Rows.Add(db.NewRow());
            db.Rows[1]["Имя"] = "Петр";
            db.Rows[1]["Фамилия"] = "Петров";
 
            GridView gv = new GridView();
 
            foreach (DataColumn item in db.Columns)
            {
                GridViewColumn gv_col = new GridViewColumn
                {
                    Header = item.ColumnName,
                    DisplayMemberBinding = new Binding(item.ColumnName)
                };
 
                gv.Columns.Add(gv_col);
            }
 
            DataList.View = gv;
 
            DataList.Items.Refresh();
        }
 
        private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (DataList.SelectedItem is DataRowView rowView)
            {
                MessageBox.Show(string.Format("{0} {1}", rowView.Row["Имя"], rowView.Row["Фамилия"]));
            }
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            LoadMyList();
        }
    }
}
Файл проекта
Вложения
Тип файла: rar ListView_column.rar (74.9 Кб, 7 просмотров)
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.02.2020, 12:50
Ответы с готовыми решениями:

Динамическое заполнение ListView в WPF
Народ, возникла проблемка. Существует: &lt;ListView x:Name=&quot;LV1&quot; Margin=&quot;0,108,0,0&quot;/&gt; Я не знаю...

Динамическое заполнение combobox
Люди добрые, подскажите пожалуйста, каким образом можно заполнить combobox динамическими данными?...

Заполнение ListView
Привет всем столкнулся с такой проблемой: есть следующий ListView &lt;ListView Height=&quot;313&quot;...

Заполнение ListView
Создаю в xaml-разметке чистый ListView. Мне его надо заполнить программно. Причем количество...

15
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
07.02.2020, 16:36 2
mserg1972, WPF - это инструмент специально созданный для реализации View в паттерне MVVM.
Без MVVM - это "микроскоп для забивания гвоздей".
Почитайте обучающие темы из подписи моего поста.

MVVM начинают реализовывать с Модели - слоя данных отвечающего за обработку ДАННЫХ (их генерация, сохранение, восстановление, изменение и т.д.).

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

У вас же надо отобразить записи всегда имеющие заранее заданные свойства.

Дальше, для упрощения, буду показывать не отдельную Модель, а совмещённую Model+ViewModel.
Это не совсем правильно, но кода писать меньше и лучше подходит для формата сообщений в теме.

Создайте тип Person с нужными свойствами.
Так как этот тип предназначен для использования в View, то он должен реализовывать INPC.
Базовый класс с реализацией INPC возьмите отсюда Новая реализация OnPropertyChangedClass [WPF, Элд Хасп].
Скопируйте его в пространство Common своего проекта.

Сам класс Person
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using Common;
 
namespace ListViewTest
{
    public class Person : OnPropertyChangedClass
    {
        private string _firstName;
        private string _lastName;
        public string FirstName { get => _firstName; set => SetProperty(ref _firstName, value); }
        public string LastName { get => _lastName; set => SetProperty(ref _lastName, value); }
 
        public Person() { }
        public Person(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }
    }
}
Теперь вам надо создать Model+ViewModel которая будет генерировать данные для вашего списка по команде.
Для команды используем класс Новая реализация RelayCommand с исправлениями от proa33 и kolorotur [WPF, Элд Хасп]
Так же копируете его в пространство Common

Сам класс PersonsMVM
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
using Common;
using System.Collections.ObjectModel;
using System.Windows;
 
namespace ListViewTest
{
    public class PersonsMVM : OnPropertyChangedClass
    {
        public ObservableCollection<Person> Persons { get; }
            = new ObservableCollection<Person>();
 
        public void LoadData()
        {
            Persons.Add(new Person("Иван", "Иванов"));
            Persons.Add(new Person("Пётр", "Петров"));
        }
 
        public RelayCommand LoadDataCommand { get; }
        public RelayCommand ViewPersonCommand { get; }
 
        public PersonsMVM()
        {
            LoadDataCommand = new RelayCommand(p => LoadData());
 
            /// Вызов окна из VM - это плохо
            /// Так сделано только для упрощения демонстрации
            ViewPersonCommand = new RelayCommand
                (
                    p => { { if (p is Person person) MessageBox.Show($"{person.FirstName} {person.LastName}"); } },
                    p => p is Person
                ) ;
        }
    }
}
Теперь можно приступить к созданию View.

UserControl - не самостоятельный элемент.
Он используется внутри окна и получает контекст данных от окна.
Поэтому в MyList только указывается тип Контекста Данных.
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<UserControl x:Class="ListViewTest.MyList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:ListViewTest"
             mc:Ignorable="d" d:DataContext="{x:Type local:PersonsMVM}"
             d:DesignHeight="500" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MyList" Background="#FF2EEE0F" 
                Command="{Binding LoadDataCommand, Mode=OneWay}" />
        <ListView x:Name="DataList" Grid.Row="1" Background="#FFE4F3EF"
                  MouseDoubleClick="ListView_MouseDoubleClick"
                  ItemsSource="{Binding Persons}"/>
    </Grid>
</UserControl>
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System.Windows.Controls;
using System.Windows.Input;
 
namespace ListViewTest
{
    /// <summary>Логика взаимодействия для MyList.xaml</summary>
    public partial class MyList : UserControl
    {
        public MyList() => InitializeComponent();
 
        private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (DataContext is PersonsMVM persons && persons.ViewPersonCommand.CanExecute(DataList.SelectedItem))
                persons.ViewPersonCommand.Execute(DataList.SelectedItem);
        }
    }
}
В самом же окне можно создать Контекст Данных, который потом будет наследоваться UserControl
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<Window x:Class="ListViewTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ListViewTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen" >
    <Window.DataContext>
        <local:PersonsMVM/>
    </Window.DataContext>
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MainWindow" Background="#FFEEEE24"
                Command="{Binding LoadDataCommand, Mode=OneWay}"/>
        <local:MyList Grid.Row="1" x:Name="DataTable"/>
    </Grid>
</Window>
C#
1
2
3
4
5
6
7
8
9
10
using System.Windows;
 
namespace ListViewTest
{
    /// <summary>Логика взаимодействия для MainWindow.xaml</summary>
    public partial class MainWindow : Window
    {
        public MainWindow() => InitializeComponent();
    }
}
P.S. Коды написал, НО не отлаживал.
Если проскочат мелкие ошибки - напишите.
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
07.02.2020, 16:37 3
mserg1972, не обратил внимание.
У вас же в ListView не заданы колонки!

Вот с колонками
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
<UserControl x:Class="ListViewTest.MyList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:ListViewTest"
             mc:Ignorable="d" d:DataContext="{x:Type local:PersonsMVM}"
             d:DesignHeight="500" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MyList" Background="#FF2EEE0F" 
                Command="{Binding LoadDataCommand, Mode=OneWay}" />
        <ListView x:Name="DataList" Grid.Row="1" Background="#FFE4F3EF"
                  MouseDoubleClick="ListView_MouseDoubleClick"
                  ItemsSource="{Binding Persons}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Имя" DisplayMemberBinding="{Binding FirstName}"/>
                    <GridViewColumn DisplayMemberBinding="{Binding LastName}" Header="Фамилия"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</UserControl>
0
1 / 1 / 2
Регистрация: 18.12.2013
Сообщений: 239
08.02.2020, 08:19  [ТС] 4
Большое спасибо Элд я буду разбираться в предложенной вами реализации, но у меня стояла главная задача, которая у вас полностью перечеркнута в предложенном варианте. Мне не известны заранее наименования столбцов. Тот пример который я выложил-начальный этап, следующий этап получение данных из базы MySQL, где множество разных таблиц, которые я собираюсь выводить в созданном шаблоне. Это прямо указано у меня в условии вопроса......"...Задача состояла заполнить ListView не указывая наименования столбцов в в разметке XAML...."!!!
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
08.02.2020, 08:47 5
Цитата Сообщение от mserg1972 Посмотреть сообщение
Это прямо указано у меня в условии вопроса......"...Задача состояла заполнить ListView не указывая наименования столбцов в в разметке XAML...."!!!
Принципиально это ничего не меняет.
Но сама постановка такой задачи сомнительна. О чём я и написал сразу.
Скорее всего вы неправильно проектируете архитектуру своего приложения.

Что такое разные таблицы в БД?
Это значит, что имеются различные ТИПЫ данных.
Каждая таблица - свой тип данных.
Сделайте получение данных из БД используя EF.
Этот подход многократно сокращает код и ускоряет реализацию приложения.
Но для каждой таблицы обязательно будет свой тип данных.

На уровне же WPF View каждый тип данных требует своего шаблона представления.

Возможно, у вас очень специфическое приложение, на этот случай скину вам решение и с DataTable.
Но наиболее вероятно, у вас заложена неправильная архитектура в приложение.
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
08.02.2020, 09:58 6
Цитата Сообщение от mserg1972 Посмотреть сообщение
Задача состояла заполнить ListView не указывая наименования столбцов в в разметке XAM
Класс Модели
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.Collections.Generic;
 
namespace ListViewTest
{
    /// <summary>Класс Model</summary>
    public class PersonsDtModel
    {
        /// <summary>Некий набор данных поступающий из БД
        /// В реальном приложении вместо этого должен
        /// быть запрос в Базу Данных</summary>
        private Person[] Persons { get; } =
            {
                new Person("Иван", "Иванов"),
                new Person("Пётр", "Петров")
            };
 
        /// <summary>Метод возварщающий из Модели все Person.
        /// Где и как они хранятся от вышестояших слоёв
        /// скрыто.</summary>
        public IEnumerable<Person> LoadPersons()
            => Persons;
    }
}
Класс 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
67
68
69
70
71
72
73
74
using Common;
using System;
using System.Data;
using System.Windows;
 
namespace ListViewTest
{
    /// <summary>Класс ViewModel</summary>
    public class PersonsDtVM : OnPropertyChangedClass
    {
        /// <summary>Ссылка на Модель</summary>
        private readonly PersonsDtModel model
            = new PersonsDtModel();
 
        /// <summary>Команда загруски данных</summary>
        public RelayCommand LoadDataCommand { get; }
        /// <summary>Команда показа переданного Person</summary>
        public RelayCommand ViewPersonCommand { get; }
 
        private Type _nameType;
        /// <summary>Тип данных в таблице</summary>
        public Type NameType { get => _nameType; private set => SetProperty(ref _nameType, value); }
 
        private DataTable _table;
        /// <summary>Таблица с данными</summary>
        public DataTable Table { get => _table; private set => SetProperty(ref _table, value); }
 
        /// <summary>Инициализирует Таблицу для разных типов данных
        private void InitTable(Type nameType)
        {
            /// Если тип тот же, то инициализация не требуется
            if (NameType == nameType)
                return;
 
            NameType = nameType;
            DataTable table = new DataTable();
            if (NameType == typeof(Person))
            {
                table.Columns.Add(new DataColumn("Имя", typeof(string)));
                table.Columns.Add(new DataColumn("Фамилия", typeof(string)));
            }
            Table = table;
        }
 
        /// <summary>Метод загрузки в таблицу данных,
        /// полученых из Модели</summary>
        private void LoadData(Type nameType)
        {
            InitTable(nameType);
 
            if (NameType == typeof(Person))
                foreach (Person person in model.LoadPersons())
                {
                    DataRow newRow = Table.NewRow();
                    newRow["Имя"] = person.FirstName;
                    newRow["Фамилия"] = person.LastName;
                    Table.Rows.Add(newRow);
                }
        }
        public PersonsDtVM()
        {
            LoadDataCommand = new RelayCommand(p => LoadData(typeof(Person)));
 
            /// Вызов окна из VM - это плохо
            /// Так сделано только для упрощения демонстрации
            /// Как здесь отображать любой тип с неизвестным кличеством свойств и их типа ?
            ViewPersonCommand = new RelayCommand
                (
                    p => { { if (p is DataRowView dataRow) MessageBox.Show($"{dataRow["Имя"]} {dataRow["Фамилия"]}"); } },
                    p => p is DataRowView
                );
        }
    }
}
UserControl
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<UserControl x:Class="ListViewTest.MyListDt"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:ListViewTest"
             mc:Ignorable="d" d:DataContext="{x:Type local:PersonsDtVM}"
             d:DesignHeight="500" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MyList" Background="#FF2EEE0F" 
                Command="{Binding LoadDataCommand, Mode=OneWay}" />
        <DataGrid x:Name="DataList" Grid.Row="1" Background="#FFE4F3EF"
                  MouseDoubleClick="ListView_MouseDoubleClick"
                  ItemsSource="{Binding Table, Mode=OneWay}"
                  IsReadOnly="True"/>
 
    </Grid>
</UserControl>
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System.Windows.Controls;
using System.Windows.Input;
 
namespace ListViewTest
{
    /// <summary>Логика взаимодействия для MyList.xaml</summary>
    public partial class MyListDt : UserControl
    {
        public MyListDt() => InitializeComponent();
 
        private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (DataContext is PersonsDtVM persons && persons.ViewPersonCommand.CanExecute(DataList.SelectedItem))
                persons.ViewPersonCommand.Execute(DataList.SelectedItem);
        }
    }
}
Окно
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
<Window x:Class="ListViewTest.MainWindowDt"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ListViewTest"
        mc:Ignorable="d"
        Title="MainWindowDt" Height="450" Width="800" WindowStartupLocation="CenterScreen" >
    <Window.DataContext>
        <local:PersonsDtVM/>
    </Window.DataContext>
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MainWindow" Background="#FFEEEE24"
                Command="{Binding LoadDataCommand, Mode=OneWay}"/>
        <TextBlock Grid.Row="1">
            <Run Text="{Binding NameType.Namespace, Mode=OneWay}"/>
            <Run Text="{Binding NameType.Name, Mode=OneWay}"/>
        </TextBlock>
        <local:MyListDt Grid.Row="2" x:Name="DataTable"/>
    </Grid>
</Window>
C#
1
2
3
4
5
6
7
8
9
10
using System.Windows;
 
namespace ListViewTest
{
    /// <summary>Логика взаимодействия для MainWindow.xaml</summary>
    public partial class MainWindowDt : Window
    {
        public MainWindowDt() => InitializeComponent();
    }
}
0
1 / 1 / 2
Регистрация: 18.12.2013
Сообщений: 239
08.02.2020, 11:13  [ТС] 7
Да, но теперь данные выводятся не в ListView, а в DataGrid?

Объясню более подробно чего я добиваюсь:
Есть Основное окно с меню
В основном окне есть вложенное окно, в котором размещен ListView
XML
1
<local:MyList Grid.Row="1" x:Name="DataTable"/>
Есть база MySql в которой две таблицы - tbl_city и tbl_shop
Соответственно в меню главного окна есть два субменю по по нажатию на которые Шаблон ListView
заполняется данными из первой или второй таблицы.
При этом необходимое условие, что количество столбцов в таблицах разное,они связанные по некоторым полям, таблицы могут добавляться другие и редактироваться.
Как достать данные из базы и разместить их в ListView, если он расположен в главном окне и заранее известны столбцы- я знаю.
А вот если ListView размещен в отдельном контроле и не известны заранее столбцы, я не знаю.
В DataGrid проще, там не надо указывать столбцы, а в List View я нашел только ту реализацию которую изложил в начале темы.
0
966 / 722 / 233
Регистрация: 30.04.2009
Сообщений: 2,997
08.02.2020, 11:20 8
Если нужен просто quick fix, а не нравоучения как делать правильно, то в обработчике button click в main window надо обращаться к существующему UI элементу
DataTable.LoadMyList();
1
1 / 1 / 2
Регистрация: 18.12.2013
Сообщений: 239
08.02.2020, 11:23  [ТС] 9
Нет, я же написал в начале темы, что надо помочь реализовать мою задумку и попросил так же предложить правильное решение, но с учетом задачи изложенной в задании.
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
08.02.2020, 11:55 10
mserg1972, вы неправильно решаете задачу!
Самая принципиальная ошибка - это создание данных внутри View.
Вторая ошибка - это получение данных UI элементом самостоятельно, а не от родительского окна.

А отображает их DataGrid или ListView - какая разница?
В WPF элементы выбираются по ПОВЕДЕНИЮ, а не по внешнему виду.
Одно из проведений DataGrid - это автогенерация колонок по привязанной таблице.
Какой смысл использовать ListView где эту автогенерацию придётся делать кодом?
Что такого даёт ListView чего нет у DataGrid?
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
08.02.2020, 12:15 11
Лучший ответ Сообщение было отмечено mserg1972 как решение

Решение

Вот решение с ListView - кроме кучи дополнительного кода оно ничего не даёт
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<UserControl x:Class="ListViewTest.MyListDtLV"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:ListViewTest"
             mc:Ignorable="d" d:DataContext="{x:Type local:PersonsDtVM}"
             d:DesignHeight="500" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MyList" Background="#FF2EEE0F" 
                Command="{Binding LoadDataCommand, Mode=OneWay}" />
        <ListView x:Name="DataList" Grid.Row="1" Background="#FFE4F3EF"
                  MouseDoubleClick="ListView_MouseDoubleClick"
                  ItemsSource="{Binding Table, Mode=OneWay}"
                  />
 
    </Grid>
</UserControl>
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
using System.ComponentModel;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
 
namespace ListViewTest
{
    /// <summary>Логика взаимодействия для MyList.xaml</summary>
    public partial class MyListDtLV : UserControl
    {
        public MyListDtLV()
        {
            DataContextChanged += MyListDtLV_DataContextChanged;
            InitializeComponent();
 
        }
 
        private PersonsDtVM viewModel;
 
        private void MyListDtLV_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (viewModel != null)
                viewModel.PropertyChanged -= ViewModel_PropertyChanged;
 
            viewModel = e.NewValue as PersonsDtVM;
 
            if (viewModel != null)
                viewModel.PropertyChanged += ViewModel_PropertyChanged;
        }
 
        private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(PersonsDtVM.Table))
            {
                GridView gv = new GridView();
                foreach (DataColumn item in viewModel.Table.Columns)
                {
                    GridViewColumn gv_col = new GridViewColumn
                    {
                        Header = item.ColumnName,
                        DisplayMemberBinding = new Binding(item.ColumnName)
                    };
 
                    gv.Columns.Add(gv_col);
                }
 
                DataList.View = gv;
 
                DataList.Items.Refresh();
            }
 
        }
 
        private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (DataContext is PersonsDtVM persons && persons.ViewPersonCommand.CanExecute(DataList.SelectedItem))
                persons.ViewPersonCommand.Execute(DataList.SelectedItem);
        }
    }
}
Окно
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
<Window x:Class="ListViewTest.MainWindowDtLV"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ListViewTest"
        mc:Ignorable="d"
        Title="MainWindowDtLV" Height="450" Width="800" WindowStartupLocation="CenterScreen" >
    <Window.DataContext>
        <local:PersonsDtVM/>
    </Window.DataContext>
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Загрузить из MainWindow" Background="#FFEEEE24"
                Command="{Binding LoadDataCommand, Mode=OneWay}"/>
        <TextBlock Grid.Row="1">
            <Run Text="{Binding NameType.Namespace, Mode=OneWay}"/>
            <Run Text="{Binding NameType.Name, Mode=OneWay}"/>
        </TextBlock>
        <local:MyListDtLV Grid.Row="2" x:Name="DataTable"/>
    </Grid>
</Window>
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
08.02.2020, 13:29 12
mserg1972, конкретно, по вашему коду, если вы так сильно хотите его придерживаться, то ошибка у вас в том, что вместо вызова метода существующего контрола, создаёте новый контрол, но который ни где не показывается.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Windows;
 
namespace ListViewTest
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          //  MyList milist = new MyList();
           /* milist */ DataTable.LoadMyList();
        }
    }
}
Но это КОСТЫЛЬ!
Решение созданное из таких костылей поддерживать ооочень проблематично.
1
1 / 1 / 2
Регистрация: 18.12.2013
Сообщений: 239
11.02.2020, 11:25  [ТС] 13
Не могу понять что не так? Все вроде работало, а теперь в LIst выводит вместо имен и фамилий - "ListViewTest.Person"
Во вложении проект

Вложение -Проект
Вложения
Тип файла: rar ListView.rar (397.8 Кб, 8 просмотров)
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
11.02.2020, 12:38 14
Цитата Сообщение от mserg1972 Посмотреть сообщение
теперь в LIst выводит вместо имен и фамилий - "ListViewTest.Person"
Ну, так вы же не string, а сложный тип выводите.
Надо задать или шаблон элемента.
Или, если выводить только одно свойство, укажите это свойство в DisplayMemberPath
0
1 / 1 / 2
Регистрация: 18.12.2013
Сообщений: 239
14.02.2020, 10:24  [ТС] 15
Элд, как понять ваше замечание "...
/// Вызов окна из VM - это плохо
/// Так сделано только для упрощения демонстрации..", а откуда вызывать тога? Допустим сообщение об ошибке или MessageBox ?
0
Модератор
Эксперт .NET
10848 / 7695 / 2087
Регистрация: 21.04.2018
Сообщений: 23,178
Записей в блоге: 2
14.02.2020, 17:43 16
Цитата Сообщение от mserg1972 Посмотреть сообщение
Элд, как понять ваше замечание "...
С учётом того, что вы знаете сто такое MVVM, не буду углубляться в мелочи.
Но если что непонятно - поинтересуйтесь.


"Ошибка" это очень неконкретный термин:

1) Есть "валидация вводимых пользователем значений" - это функция View, есть специальные механизмы для этого и VM просто не задействована в такой валидации.

2) Есть "исключения" они любо обрабатываются на месте, либо "прокидываются" на верхние уровня и в конечном итоге доходят до View где или View их обрабатывает (допусти выводит сообщение), либо прерывается выполнение приложения.

3) Есть ошибки обработки данных, но не являющиеся исключениями. Это похоже на ваш случай: Ошибка в ViewModel о которой надо вывести сообщение пользователю. В общем случае это подобно выводу из ViewModel любого сообщения.
Сама VM ничего никуда вывести не может. Но она может сформировать нужное сообщение и сообщить об этом View или App.
Один из способов это сделать, создать в VM событие MessageEvent с параметрами object sender и string message. В App создаётся метод с такими же параметрами. В методе происходит модальный вызов окна с передачей ему message для показа. В качестве окна может быть вызван MessageBox или кастомное окно. При старте (в событии Startup или методе OnStartup) App инициализирует ViewModel? подписывает свой метод на событие VM, потом создаёт окно и передаёт ему в Контекст Данных созданную VM.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.02.2020, 17:43

Заполнение listview
Подскажите, как добавить столбцы и заполнить строки, при нажатии кнопки?

Динамическое создание и заполнение combobox
Добрый день. Подскажите, пожалуйста, как решить задачу. При нажатии на кнопку на форму...

Заполнение ListView из коллекции
Подскажите как осуществить привязку данных в ListView item source из ObservableCollection Есть...

Заполнение ListView из XAML
Здравствуйте, есть такая проблемка, у меня есть класс public class Person { public...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru