wpf привязка (обновление данных)

224
03 марта 2019, 22:10

есть класс Project (модель) с некиеми методами:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.IO;
using System.Xml;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace ReadAndVerify
{
    [Serializable]
    public class Project : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        [XmlIgnore]
        private static string pathToFile = @"..\..\Xml\Project.xml";
        [XmlIgnore]
        private string title;
        [XmlIgnore]
        private DateTime startDateForProject;
        [XmlIgnore]
        private DateTime finishDateForProject;
        public string Title { get { return title; } set { title = value; RaisePropertyChanged("Title"); } }
        [XmlElement("StartDate")]
        public DateTime StartDateForProject { get { return startDateForProject; } set { startDateForProject = value; RaisePropertyChanged("StartDateForProject"); } }
        [XmlElement("FinishDate")]
        public DateTime FinishDateForProject { get { return finishDateForProject; } set { finishDateForProject = value; RaisePropertyChanged("FinishDateForProject"); } }
        public Project() { }
        public Project(string title,DateTime startDate, DateTime finishDate)
        {
            Title = title;
            StartDateForProject = startDate;
            FinishDateForProject = finishDate;
            //DayOfProject = 10;
        }
        public static ObservableCollection<MyDictionary> getTheurrentPercentageOfTheDayOfProjectExecution(List<Project> projects)
        {
            ObservableCollection<MyDictionary> result = new ObservableCollection<MyDictionary>();
            foreach (Project _project in projects)
            {
                // Сколько всего дней для проекта (100%)
                int maxDate = _project.FinishDateForProject.Subtract(_project.StartDateForProject).Days;
                // Сколько прошо дней (кол-во)
                int curentDate = DateTime.Now.Subtract(_project.StartDateForProject).Days;
                // Текущий процен пройденых дней
                result.Add(new MyDictionary(_project.Title, curentDate * 100 / maxDate));
            }
            return result;
        }
        protected virtual void RaisePropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, e);
        }
        protected void RaisePropertyChanged(string propertyName)
        {
            RaisePropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }
}

Во ViewModel есть переменная project, которая содержит в себе все проекты с xml файла (биндится DataGrit Mode = TwoWay) для редактирования данных каждого проекта. Отображение идет в другом окне через прогресс бары + текстблок отдельной переменной, которая заполняется методом getTheurrentPercentageOfTheDayOfProjectExecution() класса Project. Класс MyDictionary имеет реализацию интерфейса INotifyPropertyChanged. Key - это название проекта, Value- это процент прогресс бара.

Проблема: если я изменяю список проектов, и на кнопке сохранить вызываю заново метод getTheurrentPercentageOfTheDayOfProjectExecution, то почему прогресс бары и названия с коллекции ObservableCollection автоматом не подтягиваются? (Возможно что-то еще из кода понадобится...)

Answer 1

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

То есть если у нас есть

public ObservableCollection<string> TestData { get; set; } = new ObservableCollection<string>();

с привязкой <ListBox ItemsSource="{Binding TestData}"/>.

То если мы напишем TestData = new ObservableCollection<string>(); - наша привязка пропадет, ибо мы привязались к старой копии объекта.

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

foreach (var item in AddData())
    TestData.Add(item);

Теперь что касается обновления. В MVVM (да и вообще в ООП) принято разбивать всю логику по своим классам, которые отвечают только за этот объект. Скажем есть у нас человек, делаем класс class Person{}. Человек имеет руки, ноги, голову, пусть это будут наши свойства (public Hand[] Hands {get; set;}, public Head Head {get; set;} ...). Также человек может выполнять какие то действия, например идти, это по сути тоже метод класса Person (public void Walk(int speed){...}). Как видите все это относится к человеку логично это все реализовывать именно в классе человека, а не относить скажем ходьбу к классу сердца. Также и у вас, вы делаете коллекцию неких объектов у которых есть своя логика, так почему бы не написать метод обновления внутри этой ViewModel?

Пример:

Делаем некий класс (VM):

public class TestData
{
    public TestData(string name, int percent)
    {
        Name = name;
        Percent = percent;
    }
    public string Name { get; set; }
    public int Percent { get; set; }
    public void Update() => Percent++;
}

Делаем коллекцию с тестовыми данными:

public ObservableCollection<TestData> TestCollection { get; set; } = new ObservableCollection<TestData>
{
    new TestData("Item 1", 0),
    new TestData("Item 2", 1),
    new TestData("Item 3", 2),
    new TestData("Item 4", 3)
};

Далее предположим, что мы ее привязали, все у нас работает. Надо теперь обновить данные, мы делаем следующее:

Если всю коллекцию, то:

foreach (var testData in TestCollection)
    testData.Update();

Если один элемент:

TestCollection.FirstOrDefault(x => x.Name == "Item 3")?.Update();

Как видите мы нечего не передобавляем, мы работаем с тем, что уже имеем. Так что советую вам тоже попробовать это реализовать, отказавшись от каких то статичных методов...

Удачи в изучении WPF!

READ ALSO
Как достать список из таблицы БД?

Как достать список из таблицы БД?

Я получил список категорий из БДДалее мне нужно получить из соседней таблицы все топики, которые относятся к данной категории

300
символ " в запросе (C#)

символ " в запросе (C#)

Как вставить код символа в запрос С#? В месте, где я указываю на формат даты:

206
Примитивы синхроинзации

Примитивы синхроинзации

Вопрос теоретический, делал я задачу тестовую для VeeamЗнаменитая задача про архиватор многопоточный

245