Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273

Отложенная загрузка ветвей TreeView через команды в MVVM

09.04.2025, 14:42. Показов 3373. Ответов 32

Студворк — интернет-сервис помощи студентам
Здравствуйте, помогите, пожалуйста, разобраться. Как сделать отложенную загрузку ветвей в TreeView.

Есть следующие классы сущностей (на названия не обращайте внимание изменены специально):

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
public class GeneralObject
{
    public int Id { get; set; }
    public string Product { get; set; }
    public BitmapSource IconType { get; set; }
    public BitmapSource IconState { get; set; }
}
 
public class Materials : GeneralObject
{
    public string Number { get; set; }
    public List<TypeFolder> TypeFolders { get; set; }
}
 
public class TypeFolder : GeneralObject
{
    public List<Shop> Shops { get; set; }
}
 
public class Shop : GeneralObject
{
    public string Code { get; set; }
    public string Site { get; set; }
 
    public List<Something> Somethings { get; set; }
}
 
public class Something : GeneralObject
{
    public byte[] File { get; set; }
    public Shop Parent { get; set; }
}
Вот так дерево сделано в 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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<TreeView Grid.Row="1"
          x:Name="tree"
          BorderBrush="Black"
          BorderThickness="0.5"
          Width="Auto"
          Margin="3"
          ItemsSource="{Binding Materials}">
 
    <TreeView.Resources>
        <DataTemplate x:Key="BaseItemTemplate">
            <StackPanel Orientation="Horizontal"
                        VerticalAlignment="Center">
 
                <Image Source="{Binding IconType}"
                       Height="16"
                       Width="16"
                       Margin="3,0,0,0"/>
 
                <Image Source="{Binding IconState}"
                       Height="16"
                       Width="16"
                       Margin="3,0,3,0"/>
 
                <TextBlock Text="{Binding Product}"
                           FontSize="14"/>
            </StackPanel>
        </DataTemplate>
 
        <HierarchicalDataTemplate DataType="{x:Type model:Materials}"
                                  ItemsSource="{Binding TypeFolders}">
            <ContentPresenter Content="{Binding}" 
                              ContentTemplate="{StaticResource BaseItemTemplate}"/>
        </HierarchicalDataTemplate>
 
        <HierarchicalDataTemplate DataType="{x:Type model:TypeFolder}"
                                  ItemsSource="{Binding Shops}">
            <ContentPresenter Content="{Binding}" 
                              ContentTemplate="{StaticResource BaseItemTemplate}"/>
        </HierarchicalDataTemplate>
 
        <HierarchicalDataTemplate DataType="{x:Type model:Shop}"
                                  ItemsSource="{Binding Somethings }">
            <ContentPresenter Content="{Binding}" 
                              ContentTemplate="{StaticResource BaseItemTemplate}"/>
        </HierarchicalDataTemplate>
 
        <DataTemplate DataType="{x:Type model:Something}">
            <ContentPresenter Content="{Binding}"
                              ContentTemplate="{StaticResource BaseItemTemplate}"/>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>
В Shop список объектов Something грузится очень долго объектов много и тд и тп. и начальная инициализация окна и заполнение дерева растягивается на минуты. Необходимо сделать так, чтобы при попытке раскрыть ветвь Shop происходила загрузка списка объектов только для этой ветки. Как это можно реализовать?

пробовал через тригеры привязаться к команде, но не получается получить именно TreeViewItem, чтобы взять из него необходимые данные
XML
1
2
3
4
5
6
<b:Interaction.Triggers>
    <b:EventTrigger EventName="Expanded" SourceObject="OriginalSource"> 
        <b:InvokeCommandAction Command="{Binding LoadSomething}"
                               CommandParameter="{Binding ElementName=tree, Path=SelectedItem}"/>
    </b:EventTrigger>
</b:Interaction.Triggers>
и такое пробовал SourceObject="{x:Type TreeViewItem}"

Нужно не только чтоб по событию вызывалась команда но еще и получить объект сам TreeViewItem чтобы по его Id загрузить дочерние элементы

Есть еще вопрос по поводу съедает ли BitmapSource качество изображения, когда его создают из Bitmap?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.04.2025, 14:42
Ответы с готовыми решениями:

WPF команды и MVVM. Часть 2. Всплытие команд. Реализация команды для списка элементов [WPF, Элд Хасп]
Тема из цикла https://www.cyberforum.ru/wpf-silverlight/thread2384523.html На практике часто...

Перебор всех ветвей в treeView
Имеется элемент treeView с кучей ветвей, у каждой ветки есть дочерние, у тех в свою очередь тоже...

Вывод всех ветвей TreeView в ComboBox
Здравствуйте! Есть treeview в которое пользователь добавляет свои узлы и ветви, нужно что бы они...

32
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
09.04.2025, 15:09
IIIIIIIIIgor, В TreeView есть ведь SelectedItem? Если да, то при его изменении делайте/грузите что вам нужно
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public LaborHBType SelectedLaborHBType
{
    get => _selectedLaborHBType;
    set
    {
        if (Set(ref _selectedLaborHBType, value))
        {
            if (_selectedLaborHBType != null)
            {
                // Тут делаем что надо при изменении свойства
                ClearTypeFields();
                _taskQueue.QueueBackgroundWorkItem(LoadWorksDataAsync);
            }
        }
    }
}
0
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273
09.04.2025, 15:31  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
В TreeView есть ведь SelectedItem
что-то не могу понять, как в моей структуре TreeView получить SelectedItem. Через триггер и свойство SelectedItemChanged ?
или как-то можно чтобы в конкретном HierarchicalDataTemplate срабатывало это?

и при раскрытии ветви SelectedItem не будет пустым, мы же на саму ветку не нажимали?
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
09.04.2025, 15:37
IIIIIIIIIgor, Почитайте - Data binding to SelectedItem in a WPF Treeview.

Добавлено через 2 минуты
IIIIIIIIIgor, Вот ещё варианты - WPF MVVM TreeView SelectedItem. Сам не пробовал ни этот, ни выше который...
0
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273
09.04.2025, 15:54  [ТС]
Andrey-MSK, Сделал следующим образом, через команду а не свойство:

C#
1
2
3
4
5
6
7
8
9
10
public ICommand SelectItemTreeCommand { get; }
private bool CanSelectItemTreeCommand(object p) => true;
private void OnSelectItemTreeCommand(object p)
{
    if (p is Shop)
    {
        var shop = p as Shop;
        ...
    }
}
в xaml в сам TreeView добавил:
XML
1
2
3
4
5
6
<b:Interaction.Triggers>
    <b:EventTrigger EventName="SelectedItemChanged" SourceObject="{Binding ElementName=tree}">
        <b:InvokeCommandAction Command="{Binding SelectItemTreeCommand}"
                               CommandParameter="{Binding ElementName=tree, Path=SelectedItem}"/>
    </b:EventTrigger>
</b:Interaction.Triggers>
Но это не то чего я хотел, сейчас чтобы сработало и зашло в команду надо непосредственно нажать на нужную ветку в дереве, а я хотел бы, чтобы надо было попробовать ее раскрыть и потом начиналась бы загрузка. И второй момент головной объект дерева у меня объявлен как :

C#
1
2
3
4
5
6
private ObservableCollection<Materials > _materials  = new ObservableCollection<Materials >();
public ObservableCollection<Materials > Materials 
{
    get => _materials  ;
    set { _materials  = value; OnPropertyChanged(); }
}
почему не срабатывает обновление дерева в интерфейсе после того как нужные объекты добавились в один из дочерних объектов Materials ?
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
09.04.2025, 16:15
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
а я хотел бы, чтобы надо было попробовать ее раскрыть и потом начиналась бы загрузка.
Ну дак привяжитесь к SelectedItem, и в свойстве делайте что нужно, как у меня в примере.
XML
1
<TreeView ItemsSource="{Binding ...}" SelectedItem="{Binding ...}" ... />
Когда значение свойства меняется, проверяйте что там появилось и в зависимости от этого принимайте решение в методе set() привязанного свойства.
По второй ссылке там рассказано как сделать привязку.

Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
C#
1
2
3
4
5
6
private ObservableCollection<Materials > _materials  = new ObservableCollection<Materials >();
public ObservableCollection<Materials > Materials 
{
    get => _materials  ;
    set { _materials  = value; OnPropertyChanged(); }
}
Вот так делать с этим типом коллекции не нужно. Достаточно
C#
1
public ObservableCollection<Materials> Materials { get; } = new ObservableCollection<Materials>();
Это свойство должно быть только для чтения. Все манипуляции с коллекцией производить через Add(), Remove(), RemoveAt() и [] в приватных методах VM.
0
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273
09.04.2025, 16:32  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Ну дак привяжитесь к SelectedItem
не знаю как у вас это получилось, мне не дает к нему привязаться
пробую также ошибка: Свойство "SelectedItem" не имеет доступного метода задания. И мне не нужно нажимать на саму ветку, чтобы пойти собирать доп объекты, мне надо чтоб нажали на значок раскрытия ветки и пошли выполняться действия

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Это свойство должно быть только для чтения
суть в том, что когда обновилось свойство одного из вложенных объектов, в интерфейсе ничего не поменялось , не отобразился список дочерних узлов
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
09.04.2025, 16:50
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
суть в том, что когда обновилось свойство одного из вложенных объектов, в интерфейсе ничего не поменялось , не отобразился список дочерних узлов
Добавить для класса этого объекта поведение INotifyPropertyChanged, тогда всё будет обновлять. Это гораздо экономичнее по ресурсам, чем пересоздавать каждый раз коллекцию.
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
не знаю как у вас это получилось
У меня ничего не получалось, я вам сразу сказал что не пробовал. Я просто вас направляю на пути поиска истины Тем более в первой ссылке есть пример как создать это свойство и работать с ним.

Вот еще нечто похожее на ваше - Получить выбранный элемент в дереве TreeView MVVM

Добавлено через 3 минуты
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
мне не дает к нему привязаться
Странно, но привязка к нему разрешена...
C#
1
2
[System.ComponentModel.Bindable(true)]
public object SelectedItem { get; }
TreeView.SelectedItem.
Или они опять его спрятали, как SelectedItems в DataGrid...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,142
Записей в блоге: 2
09.04.2025, 17:26
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
я хотел бы, чтобы надо было попробовать ее раскрыть и потом начиналась бы загрузка.
Вам нужно не событие SelectedItemChanged, а событие TreeViewItem.Expanded.

Но можно внедрить логику ленивой загрузки и в сами элементы на уровне VM или Модели. Но тогда простые DTO-шки не подойдут, нужны полноценные сущности со связанной логикой.

Добавлено через 1 минуту
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
public BitmapSource IconType { get; set; }
Тип BitmapSource не может находиться в ViewModel и тем более в Модели.
0
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273
09.04.2025, 17:28  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Или они опять его спрятали, как SelectedItems в DataGrid..
возможно зависит от framework я использую .net framework 4.7.2 и в нем вот так реализовано у них ридонли поле
C#
1
2
3
4
5
6
7
8
9
10
11
12
//
// Сводка:
//     Получает выделенный элемент в System.Windows.Controls.TreeView
//
// Возврат:
//     Выделенный объект в System.Windows.Controls.TreeView или значение null, если
//     нет выбранных элементов. Значение по умолчанию — null.
[Bindable(true)]
[Category("Appearance")]
[ReadOnly(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object SelectedItem => GetValue(SelectedItemProperty);
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Добавить для класса этого объекта поведение INotifyPropertyChanged
думал об этом. но надеялся, что ObservableCollection отслеживает все изменения во всех свойствах всех вложенных и не вложенных объектов. Не хотел INotifyPropertyChanged тянуть в сущности
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
09.04.2025, 17:32
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
что ObservableCollection отслеживает все изменения во всех свойствах всех вложенных и не вложенных объектов.
Этот тип реализует INotifyCollectionChanged. Это подразумевает уведомления об изменении коллекции (удаление, вставка элементов), а не свойств её вложенных элементов.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,142
Записей в блоге: 2
09.04.2025, 17:33
Цитата Сообщение от Элд Хасп Посмотреть сообщение
можно внедрить логику ленивой загрузки и в сами элементы на уровне VM или Модели.
Например:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class GeneralObject
{
    public int Id { get; set; }
    public string Product { get; set; }
 
    private byte [] _itype;
    private byte [] _istate;
 
    public byte [] IconType => _itype ??= LoadIType();
    public byte [] IconState => _istate ??= LoadIState();
 
    private byte[] LoadIType()
    {
        // Логика загрузки изображения в массив байт
        return image;
    }    
    private byte[] LoadIState()
    {
        // Логика загрузки изображения в массив байт
        return image;
    }    
}
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
09.04.2025, 17:49
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
Не хотел INotifyPropertyChanged тянуть в сущности
И не надо, нужно просто в VM сделать для них обёртки.

Добавлено через 11 минут
IIIIIIIIIgor, Ну тогда это свойство можно вот так создавать и использовать - https://stackoverflow.com/a/5118406

Добавлено через 3 минуты
IIIIIIIIIgor, И вот тут его поведение можно расширить до нужного вам
C#
1
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
Добавлено через 1 минуту
Можно сделать свойство, которое будет реагировать на раскрытие узла... Да можно вообще что угодно сделать, Behavior мощная штука
0
298 / 260 / 108
Регистрация: 26.10.2012
Сообщений: 810
10.04.2025, 08:30
Занимался такой же задачей.
Скажу, что из-за рекурсивного вызова await в TreeView все непросто. Код чувствителен к порядку вызова await и обновления Children. Дерево может обновиться асинхронно, но все и сразу; дерево может показать только самую первую свою ветвь; дерево может вообще не обновиться. Для нормального последовательного отображения новых узлов обязательно надо вызвать BindingOperations.EnableCollectionSynchr onization(node.Children) именно в главном потоке для каждого узла.
Нормально получилось так (на примере дерева папок).
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
public class FileTreeNode 
{
    public bool hasLoaded;
 
    private bool _isSelected;
    public bool IsSelected
    {
        get => _isSelected;
        set
        {
            if (_isSelected == value) return;
            _isSelected = value;
            foreach (var child in Childrens)
            {
                child.IsSelected = value;
            }
        }
    }
    public string Name { get; set; }
    public string Path { get; set; }
    public int Level { get; private init; }
    public bool IsExpanded => Level <= 2;
    public ObservableCollection<FileTreeNode> Childrens { get; } = [];
 
    private static readonly object lockObject = new();
    public static FileTreeNode CreateTreeNode(string directory)
    {
        var treeNode = new FileTreeNode
        {
            Name = directory,
            Path = directory,
            Level = 1
        };
        BindingOperations.EnableCollectionSynchronization(treeNode.Childrens, lockObject);
        Task.Run(() => CreateChildrens(treeNode));
        var root = new FileTreeNode();
        root.Childrens.Add(treeNode);
        return root;
    }
    private static async Task CreateChildrens(FileTreeNode parent)
    {
        var level = parent.Level + 1;
 
        foreach (var directory in Directory.GetDirectories(parent.Path))
        {
            var dirInfo = new DirectoryInfo(directory);
            var node = new FileTreeNode
            {
                Name = dirInfo.Name,
                Path = dirInfo.FullName,
                Level = level
            };
            //симуляция долгой работы
            await Task.Delay(100);
            //мне накидают по шапкам за доступ к Application.Current.Dispatcher, но иначе нормально не работает
            //просто вызов BindingOperations.EnableCollectionSynchronization в другом потоке не дает эффекта
            await Application.Current.Dispatcher.InvokeAsync(() =>BindingOperations.EnableCollectionSynchronization(node.Childrens, lockObject));
            parent.Childrens.Add(node);
            await CreateChildrens(node);
        }
    }
}
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<TreeView Grid.Row="1" Grid.RowSpan="2"  Grid.Column="0" ItemsSource="{Binding NodeRoot.Childrens}">
    <i:Interaction.Behaviors>
        <vm:BindableSelectedItemBehavior SelectedItem="{Binding SelectedNode, Mode=TwoWay}"/>
    </i:Interaction.Behaviors>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type vm:FileTreeNode}" ItemsSource="{Binding Childrens}">
            <TextBlock Text="{Binding Name}" FontSize="16"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=OneTime}"/>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>
0
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273
10.04.2025, 08:36  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вам нужно не событие SelectedItemChanged, а событие TreeViewItem.Expanded
я пытался на него зацепиться через триггер (писал об этом в самом вопросе), но это не дало результата никакого. Вот как с моей структурой дерева в XAML отлавливать это событие?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Тип BitmapSource не может находиться в ViewModel и тем более в Модели.
предлагаете делать конвертер который будет вызывать в самом xaml? да и сейчас не так важно где что лежит, суть в том что мне надо из массива байт сделать bitmap убрать фон (это делается отлично изображения качественные), а так как в XAML Image Source не принимает Bitmap приходится переводить еще и в BitmapSource и качество теряется картинки становятся мыльными размытыми(

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
И не надо, нужно просто в VM сделать для них обёртки.
в VM сделать отдельные свойства или что-то другое? если свойства то это все свое "дерево" в VM разбивать на разные свойства по ветвям? звучит как то не очень
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
10.04.2025, 08:44
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
в VM сделать отдельные свойства или что-то другое?
Сделайте класс, который повторяет сущность, но не обязательно полностью повторять, и добавьте в нём INPC. Потом методами VM из класса-обёртки переносить данные в сущности, хотя вместо сущностей между слоями нужно передавать DTO, а потом в модели из DTO создавать сущности. DTO/обёртки могут быть абсолютно другими нежели сущности, они нужны именно для передачи информации, но должна быть возможность из них собрать нужные сущности. В общем довольно таки индивидуальная тема и общего решения для него нет.
0
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273
10.04.2025, 08:51  [ТС]
на самом деле у меня не очень получается понять различия между сущности и DTO. я свои классы называю сущность. но вроде по определению они являются DTO объектами, так как в классах модели (или бизнес логики уже запутался как правильно) я их наполняю данными из базы, потом передаю в vm тот в окно и просто показываю данные, а потом буду брать некоторые данные для создания нового объекта.
Исходя из этого наверное я могу в эти классы добавить реализацию INPC
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,592
Записей в блоге: 4
10.04.2025, 08:56
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
Исходя из этого наверное я могу в эти классы добавить реализацию INPC
В DTO не должно быть никакой логики, в том числе INPC. Это просто набор свойств. Хотя в реальности всё и везде упрощают, но упрощать нужно с головой
0
3 / 3 / 0
Регистрация: 23.12.2016
Сообщений: 273
10.04.2025, 09:04  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
В DTO не должно быть никакой логики, в том числе INPC
получается DTO не нужны, делаю реализацию INPC в своих классах и надеюсь что это поможет отображать вновь загруженные ветки в дереве
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,142
Записей в блоге: 2
10.04.2025, 10:24
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
я пытался на него зацепиться через триггер (писал об этом в самом вопросе), но это не дало результата никакого
Если "ловите" на уровне выше источника события (в данном случае источник это TreeViewItem), то событие может быть помечено как обработанное (Handled=true) и "проскакивать" обычную привязку.
Это без проблем можно сделать в Code Behind или Behavior, но вот как сделать с помощью InvokeCommandAction не подскажу.
Я их редко использую, и в данный момент нет "под рукой" компа со Студией чтобы разобраться самому.

Добавлено через 4 минуты
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Массив байт
Но массив байт должен быть не просто матрицей рисунка, а полноценным описателем картинки.
Чтобы было понятно.
Вот у вас есть файл картинки, который показывается стандартными windows инструментами. Формат неважно какой: bmp, jpg, png и т.д.
Читаете полностью этот файл в массив байт и вот такой массив биндинг без проблем конвертирует в ImageSource.

Добавлено через 7 минут
Цитата Сообщение от IIIIIIIIIgor Посмотреть сообщение
на самом деле у меня не очень получается понять различия между сущности и DTO. я свои классы называю сущность. но вроде по определению они являются DTO объектами, так как в классах модели (или бизнес логики уже запутался как правильно) я их наполняю данными из базы, потом передаю в vm тот в окно и просто показываю данные, а потом буду брать некоторые данные для создания нового объекта.
DTO - это простой объект без логики предназначенный только для обмена данными. "Без логики" - это означает что в нём только поля и свойства. В современном Шарпе, поля не рекомендуется использовать, поэтому сейчас получается, что DTO - это только автосвойства.
Второй момент это "предназначенный только для передачи данных".
Например, ваш Materials это только автосвойства. Если он используется только для обмена данными с Моделью, то это DTO.
Но если он используется дальше в Модели для Контекста БД и удерживается в нём на отслеживании, то получается что у этого объекта есть логика отслеживания, хотя явно она и не прописана в самом типе Materials. И в таком случае его уже нельзя назвать DTO - это уже сущность.

Так же есть ещё POCO - это классы в которых есть простая логика, но не зависящая от других объектов.
Например если в Materials внедрить INPC, но использовать его только для обмена данными, то по сути это будет уже POCO.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.04.2025, 10:24
Помогаю со студенческими работами здесь

Рисую линию без MVVM все ОК. C MVVM произвольный старт
Добрый день всем. Рисую линию при помощи анимации. Все получилось -рисуется, стирается. Но у...

Приложение MVVM. Быстрая "Нестрогая MVVM" реализация
В этой теме будет размещена простая и быстрая реализация. Основная тема:...

Отложенная обработка событий
Здравствуйте, предположим, у нас есть Логика и Отображение. Отображение подписано на событие...

Побочный эффект отложенной загрузки страницы (браузер перебрасывает пользователя в начало страницы)
День добрый! Имеется ASP.NET страница, для ускорения загрузки на ней используется отложенная...

Нажатие на ветвь через Treeview и вывод в dataGridView
Добрый день. Есть форма подключенная к базе данных (Access). Слева на форме Treeview , справа...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача №1: при указании работ (справочник РаботыПоРемонтуСпецтехники),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru