0

Я хочу, чтобы после дропа файла сюда:

В accounts показывало кол-во загруженных строк,но не знаю как правильно сделать через данный паттерн. Я думал сделать напрямую во View изменения, но это уже нарушение MVVM. Буду благодарен за любую помощь!!!

ViewModel/MainVM.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test.ViewModels { class MainVM : INotifyPropertyChanged { private System.Collections.Concurrent.ConcurrentQueue<string> _accounts = default; private string _countOfBase = default;

    public string CountOfBase
    {
        get { return _countOfBase; }
        set 
        {
            if (_countOfBase == value)
            {
                return;
            }
            OnPropertyChanged(&quot;CountOfBase&quot;);
            _countOfBase = value;
        }
    }

    public System.Collections.Concurrent.ConcurrentQueue&lt;string&gt; Accounts
    {
        get { return _accounts; }
        set {
            if (_accounts == value)
            {
                return;
            }
            OnPropertyChanged(&quot;Accounts&quot;);
            _accounts = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName = &quot;&quot;)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

}

}

Views/MainWindow.xaml:

<Window Name="WindowFile" Drop="WindowFile_Drop" 
        AllowDrop="true" x:Class="Test.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:WotBrute"
        mc:Ignorable="d"
        Title="Test" Height="450" Width="800"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
         TextElement.Foreground="{DynamicResource MaterialDesignBody}"
         TextElement.FontWeight="Regular"
         TextElement.FontSize="13"
         TextOptions.TextFormattingMode="Ideal"
         TextOptions.TextRenderingMode="Auto"
         Background="{DynamicResource MaterialDesignPaper}"
         FontFamily="{DynamicResource MaterialDesignFont}">
    <DockPanel>
        <ItemsControl DockPanel.Dock="Top">
            <DockPanel>
                <Button Width="200" HorizontalAlignment="Left" Content="START" Background="Black" BorderBrush="{x:Null}" Foreground="#DDFFFFFF"/>
                <ProgressBar Margin="5 2" Padding="5 5 5 5" Height="Auto" Minimum="0" Maximum="100" Value="1" Foreground="Black" FontFamily="Comic Sans MS" BorderBrush="Black">
                    <ProgressBar.Background>
                        <SolidColorBrush Color="#B2000000"/>
                    </ProgressBar.Background>
                </ProgressBar>
            </DockPanel>
        </ItemsControl>
        <ItemsControl DockPanel.Dock="Top">
            <Grid>
                <DataGrid x:Name="toDrop" AutoGenerateColumns="False">
                    <DataGrid.Columns>
                        <DataGridTextColumn IsReadOnly="True" Header="123" Width="*"/>
                    </DataGrid.Columns>
                </DataGrid>
            </Grid>
        </ItemsControl>
        <ItemsControl x:Name="viewPanel" HorizontalAlignment="Center" VerticalAlignment="Bottom">
            <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
                <GroupBox Header="Accounts:" Margin="20" MinWidth="100">
                    <TextBlock HorizontalAlignment="Center" FontWeight="Bold" Text="{Binding Path=CountOfBase}"/>
                </GroupBox>
                <GroupBox Header="Proxy:" Margin="20" MinWidth="100">
                    <TextBlock HorizontalAlignment="Center" FontWeight="Bold">0</TextBlock>
                </GroupBox>
                <GroupBox Header="Goods:" Margin="20" MinWidth="100">
                    <TextBlock HorizontalAlignment="Center" FontWeight="Bold">0</TextBlock>
                </GroupBox>
                <GroupBox Header="Bads:" Margin="20" MinWidth="100">
                    <TextBlock HorizontalAlignment="Center" FontWeight="Bold">0</TextBlock>
                </GroupBox>
                <GroupBox Header="Exception:" Margin="20" MinWidth="100">
                    <TextBlock HorizontalAlignment="Center" FontWeight="Bold">0</TextBlock>
                </GroupBox>
            </StackPanel>
        </ItemsControl>
    </DockPanel>
</Window>

Views/MainWindow.xaml/MainWindow.xaml.cs:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Test.ViewModels;

namespace Test { /// <summary> /// Логика взаимодействия для MainWindow.xaml /// </summary> public partial class MainWindow : Window { MainVM mainVM = new MainVM(); private BindingList<MainVM> uploadData = new BindingList<MainVM>();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void WindowFile_Drop(object sender, DragEventArgs e)
    {

        if (e.Data.GetDataPresent(DataFormats.FileDrop))
        {
            // Note that you can have more than one file.
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            ConcurrentQueue&lt;string&gt; baseQueue = new ConcurrentQueue&lt;string&gt;();
            string tempLine = default;
            long countOfLines = 0;

            // Assuming you have one file that you care about, pass it off to whatever
            // handling code you have defined.

            try
            {
                using(StreamReader reader = new StreamReader(new FileStream(files[0], FileMode.Open)))
                {
                    while((tempLine = reader.ReadLine()) != null)
                    {
                        baseQueue.Enqueue(tempLine);
                        countOfLines++;
                    }
                }
            }
            catch (Exception excep)
            {

                MessageBox.Show(excep.Message);
            }

            uploadData.ListChanged += uploadData_ListChanged;
            uploadData = new BindingList&lt;MainVM&gt;() { new MainVM() { Accounts = baseQueue, CountOfBase = countOfLines.ToString() } };
            viewPanel.ItemsSource = uploadData;
        }
    }

    private void uploadData_ListChanged(object sender, ListChangedEventArgs e)
    {

    }
}

}

После дропа файла не срабатывает уведомление и кол-во строк не записывается в Header="Accounts:"

Netahaki
  • 621
  • VM оповещает V с помощью привязок, V оповещает VM также с помощью привязок (например, чекбоксы, поля ввода) и с помощью команд (клики по кнопкам и др события) – Андрей NOP Aug 19 '20 at 11:42
  • @АндрейNOP Я это всё понимаю, но меня интересует сама реализация. INotifyPropertyChanged можно использовать, когда пользователь что-то в форме меняет, насколько я понял. А у меня в форме дропается файл, поэтому у меня не срабатывает оповещение. – Netahaki Aug 19 '20 at 11:50
  • Пожалуйста вставьте код в вопрос. Ссылка не вечная, и без нее вопрос станет бесполезен для посетителей сайта. – aepot Aug 19 '20 at 13:03
  • Если изменение идет из кода, то нужен INPC, если изменение идет из UI, то там и так все будет работать. Так что лично мне ваш вопрос не понятен, если вы знаете про INPC, то в чем проблема? Без разницы кто что там изменяет, если эта "логика" меняет Property, то изменение будет видно в View слое. А по поводу файла, ну простите, лично я опасаюсь запускать проекты с названием Brute, так что все необходимое сюда, текстом. – EvgeniyZ Aug 19 '20 at 13:26
  • @EvgeniyZ Добавил код – Netahaki Aug 19 '20 at 13:57
  • А где вы тут увидели MVVM? – EvgeniyZ Aug 19 '20 at 14:01
  • @EvgeniyZ Я не сделал ещё Models, т.к. начал с каркаса приложения. – Netahaki Aug 19 '20 at 14:02
  • И при чем тут Models? Что по вашему такое MVVM? – EvgeniyZ Aug 19 '20 at 14:05
  • @EvgeniyZ Когда View обращается к ViewModels, та в свою очередь может обратиться к Models, если нужно и вернуть результат во View. Я новичек, возможно я просто не правильно понял данный паттерн. – Netahaki Aug 19 '20 at 14:09
  • MVVM позволяет разделить логику на несвязанные друг с другом слои. То есть XAML нечего не знает про VM и M слои, M слой нечего не знает про VM V слой, а VM слой является неким связующим, который берет из M слоя данные, необходимые лишь для привязки и реализует свойства. Вот в вашем окне, попробуйте удалить все, кроме конструктора, запустится ли приложение? Нет, а почему? Да потому, что у вас грубое нарушение MVVM, где View слой тесно связан с другими слоями, а также тут нету привязок вовсе. – EvgeniyZ Aug 19 '20 at 14:12
  • @EvgeniyZ Как тогда быть ? Что исправить нужно ? Или прям вообще структура неправильная ? Если да, то где можно пример проекта посмотреть ? – Netahaki Aug 19 '20 at 14:15
  • 1
    Ну структура я бы сказал в корне не правильная. Примеры - в интернете полно (даже тут на SO и даже от меня). Что исправить - уберите все x:Name из XAML, задайте DataCotext окну на класс, который будет содержать коллекцию для ItemsControl в виде публичного свойства и другие необходимые свойства, укажите им INPC, если это свойство будет меняться во время работы программы через код. Дальше делайте не viewPanel.ItemsSource = uploadData;, а ВашаГлавнаяVM.ВашаКоллекция.Add(итем);, ну или ВашаГлавнаяVM.ВашаКоллекция = uploadData;. Вот это уже будет минимум MVVM. – EvgeniyZ Aug 19 '20 at 14:34
  • 1
    По поводу Drag & Drop - Я бы сделал при помощи Attached Property и Behavior, к примеру так. У нас тут есть такой ответ, но он не совсем про то, что вам нужно, но в качестве ознакомления думаю сойдет. – EvgeniyZ Aug 19 '20 at 14:39

0 Answers0