Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/12: Рейтинг темы: голосов - 12, средняя оценка - 4.67
Casper-SC
Эксперт .NET
3638 / 1843 / 360
Регистрация: 27.03.2010
Сообщений: 5,164
Записей в блоге: 1
1

FlowDocument. Загрузка, освобождение.

01.02.2011, 22:22. Просмотров 2172. Ответов 1
Метки нет (Все метки)

Пишу новости для отображения в программе, которая будет у пользователей. Сохраняю новость в проге для создания новостей, которая есть только у меня, так:
Код сохранения FlowDocument в файл (Нажмите, чтобы развернуть)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        private void SaveDocument(String fileName)
        {
            ResourceDictionary res = richTextBox.Document.Resources;
            if (res.Contains(GO.Constants.NewsTitleKey))
                res[GO.Constants.NewsTitleKey] = this.textBoxNewsName.Text; 
            else res.Add(GO.Constants.NewsTitleKey, this.textBoxNewsName.Text);
 
            if (res.Contains(GO.Constants.NewsIsReadedKey))
                res[GO.Constants.NewsIsReadedKey] = false;
            else res.Add(GO.Constants.NewsIsReadedKey, false);
 
            if (res.Contains(GO.Constants.NewsDateKey))
                res[GO.Constants.NewsDateKey] = this.datePicker.SelectedDate.Value.Date;
            else res.Add(GO.Constants.NewsDateKey, this.datePicker.SelectedDate.Value.Date);
            using (FileStream fs = File.Create(fileName))
            {
                XamlWriter.Save(this.richTextBox.Document, fs);
            }
        }



В другой программе загружаю новости и отображаю в списке ListView:
XAML код 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<ListView Name="listViewNews" Margin="2,5,0,3" KeyUp="listBoxNews_KeyDown">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Дата" Width="130">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Height="16">
                            <Image Source="{Binding IsReaded, Converter={StaticResource BoolToPathConverterLstViewNews}}" />
                            <TextBlock Margin="8,0,0,0" Text="{Binding Date}"/>
                        </StackPanel>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="Заголовок" Width="325" DisplayMemberBinding="{Binding Title}"/>
        </GridView>
    </ListView.View>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <ContextMenu.Items>
                            <MenuItem Header="Просмотр">
                                <MenuItem.Style>
                                    <Style TargetType="{x:Type MenuItem}">
                                        <EventSetter Event="Click" Handler="clickNewsPreview"/>
                                    </Style>
                                </MenuItem.Style>
                            </MenuItem>
                            <MenuItem Header="Удалить">
                                <MenuItem.Style>
                                    <Style TargetType="{x:Type MenuItem}">
                                        <EventSetter Event="Click" Handler="clickNewsDelete"/>
                                    </Style>
                                </MenuItem.Style>
                            </MenuItem>
                        </ContextMenu.Items>
                    </ContextMenu>
                </Setter.Value>
            </Setter>
            <EventSetter Event="MouseDoubleClick"  Handler="listBoxNews_MouseDoubleClick"/>
            <EventSetter Event="KeyDown"  Handler="listBoxNews_KeyDown"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>
<FlowDocumentScrollViewer Name="newsDocumentViewer" Grid.Row="1" Grid.ColumnSpan="2" TextOptions.TextFormattingMode="Ideal" Height="304" Margin="0,9,0,0"/>


Вот класс благодаря которому я могу отобразить заголовок, дату создания и картинку прочитана ли новость в ListView
Класс NewsInfo (Нажмите, чтобы развернуть)
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
    public class NewsInfo : INotifyPropertyChanged
    {
        public String Title { get; set; }
        public DateTime Date { get; set; }
        public FileInfo FileInformation { get; set; }
 
        private Boolean isReaded;
        public Boolean IsReaded
        {
            get { return isReaded; }
            set
            {
                isReaded = value;
                OnPropertyChenged("IsReaded");
                Boolean isReadedNews = (Boolean)document.Resources[App.NewsIsReadedKey];
                if (value && isReadedNews == false)
                    SaveDocument(FileInformation.FullName);
            }
        }
 
        private FlowDocument document;
        public FlowDocument Document
        {
            get
            {
                if (document == null)
                    document = LoadDocument(FileInformation.FullName);
                return document;
            }
        }
 
        public NewsInfo(FileInfo FileInformation)
        {
            this.FileInformation = FileInformation;
            Title = (String)Document.Resources[App.NewsTitleKey];
            isReaded = (Boolean)Document.Resources[App.NewsIsReadedKey];
            Date = (DateTime)Document.Resources[App.NewsDateKey];
            document = null; //чтобы при старте программы не висели все документы в памяти, так как их может быть очень много
        }
 
        /// <summary>
        /// Сохранить текущий документ по указанному пути
        /// </summary>
        /// <param name="fileName">Полный путь и имя файла в который будет сохранён документ</param>
        private void SaveDocument(String fileName)
        {
            document.Resources[App.NewsIsReadedKey] = IsReaded;
            using (FileStream fs = File.Create(fileName))
            {
                XamlWriter.Save(document, fs);
            }
        }
 
        /// <summary>
        /// Загрузить документ
        /// </summary>
        /// <param name="fileName">Полный путь к файлу из которого будет загружен документ</param>
        /// <returns></returns>
        private FlowDocument LoadDocument(String fileName)
        {
            using (FileStream fs = File.OpenRead(fileName))
            {
                return XamlReader.Load(fs) as FlowDocument;
            }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected void OnPropertyChenged(String propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }


А вот так строю список этих новостей:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        private void LoadNewsToListBox()
        {
            DirectoryInfo directoryInfoTemp = new DirectoryInfo(GlobalSettings.AppFolders.DefaultFolderForArhiveNews);
            FileInfo[] files = directoryInfoTemp.GetFiles();
            listViewNews.Items.Clear();
            for (int i = 0; i < files.Length; i++)
                if (files[i].Extension == App.NewsExtension)
                {
                   //в конструкторе NewsInfo грузится 
                   //каждый файл новости и потом уничтожается, 
                   //для получения значений из ресурсов этого файла
                   listViewNews.Items.Add(new NewsInfo(files[i]));
                }
        }
Так вот в итоге получается, что при построении списка, каждый файл новости загружается полностью, из ресурсов получает значения в поля экземпляра класса NewsInfo. Потом после инициализации этих полей (Дата, Заголовок, Прочитана ли новость) полю document присваивается null, чтобы просто так не висел документ в памяти. Это при загрузке приложения.

То есть если скажем 50 файлов и при загрузке каждый грузится полностью, чтобы только из ресурсов получить значения и потом уничтожается. Позже, когда пользователь жмёт на новости в списке, то эта новость опять грузится. И свойству IsReaded присваивается true. И документ, который только что загрузился в окно предпросмотра полностью перезаписывается для того, чтобы в ресурсах документа обновить свойство IsReaded. Это нужно, чтобы при следующей загрузке списка эта новость отображалась как прочитанная. Вот и получается большой объём работы, ради мизерного результата.

Кто нибудь знает как можно прочитать чисто ресурсы из xaml файла? Вообще речь о FlowDocument. И как потом записать ресурсы в файл, не переписывая по новой весь файл? Или может подскажете, что можно другое тут сделать?
0
Миниатюры
FlowDocument. Загрузка, освобождение.  
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.02.2011, 22:22
Ответы с готовыми решениями:

flowdocument to pdf
Сущетствует ли возможность сохранить flowdocument как pdf файл? Спасибо.

Убрать интерфейс у FlowDocument
В продолжение этой темы. Напомню: делаю чат, искал способ отображения списка...

RichTextBox, FlowDocument и скроллинг
Здравствуйте. Немного предыстории. Я немного отдаленный от WPF, занимаюсь...

Можно ли преобразовать файлы *.docx в FlowDocument
Имея текстовые файлы в формате docx могу ли их перегнать и использовать как...

Добавление своих тегов в FlowDocument/Paragraph
Привет всем! Мне нужно создать Xaml-файл с заданной структурой: &lt;document&gt; ...

1
Casper-SC
Эксперт .NET
3638 / 1843 / 360
Регистрация: 27.03.2010
Сообщений: 5,164
Записей в блоге: 1
02.02.2011, 22:51  [ТС] 2
Вообще надо из xaml файла прочитать эту секцию:

XML
1
2
3
4
5
6
7
..........
<FlowDocument.Resources>
    <s:DateTime x:Key="date">2009-06-09</s:DateTime>
    <s:Boolean x:Key="isReaded">True</s:Boolean>
    <s:String x:Key="title">Вторая новость</s:String>
</FlowDocument.Resources>
..........
Добавлено через 23 часа 42 минуты
Всё решил проблему! Всё не просто быстро работает, а "бешено летает"! Тестировал на 100 файлах новостей каждая по 20 килобайт. До этого было 50 файлов аналогичного размера и были тормоза не реальные, при построении/перестроении списка, записи, что файл прочитан.

Код сохранения FlowDocument и другой инфы в файл (Нажмите, чтобы развернуть)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        private void SaveDocument(String fileName)
        {
            using (FileStream fs = File.Create(fileName))
            {
                using (BinaryWriter binWriter = new BinaryWriter(fs))
                {
                    binWriter.Write(false);
                    binWriter.Write(this.datePicker.SelectedDate.Value.Date.ToBinary());
                    binWriter.Write(this.textBoxNewsName.Text);
                    binWriter.Write(XamlWriter.Save(this.richTextBox.Document));
                }
            }
        }


ListView остался прежним.

Вот класс благодаря которому я могу отобразить заголовок, дату создания и картинку прочитана ли новость в ListView
Класс NewsInfo (Нажмите, чтобы развернуть)

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    public class NewsInfo : INotifyPropertyChanged
    {
        /// <summary>
        /// Заголовок
        /// </summary>
        public String Title { get; private set; }
        /// <summary>
        /// Дата
        /// </summary>
        public DateTime Date { get; private set; }
        public FileInfo FileInformation { get; private set; }
 
        private Boolean isReaded;
        /// <summary>
        /// Показывает прочитана ли новость
        /// </summary>
        public Boolean IsReaded
        {
            get { return isReaded; }
            set
            {
                if (value != isReaded && value)
                    SetReaded();
                isReaded = value;
                OnPropertyChanged("IsReaded");
            }
        }
 
        public FlowDocument Document
        {
            get { return LoadDocument(); }
        }
 
        /// <summary>
        /// Инициализировать поля класса прочитав из файла информацию о файле новости.
        /// Сам документ новости будет загружен при обращении к соответствующему свойству
        /// </summary>
        /// <param name="FileInformation"></param>
        public NewsInfo(FileInfo FileInformation)
        {
            this.FileInformation = FileInformation;
            using (FileStream fs = File.OpenRead(FileInformation.FullName))
            {
                using (BinaryReader binReader = new BinaryReader(fs))
                {
                    isReaded = binReader.ReadBoolean();
                    Date = DateTime.FromBinary(binReader.ReadInt64());
                    Title = binReader.ReadString();
                }
            }
        }
 
        /// <summary>
        /// Сохранить в текущий документ информацию, что он прочитан
        /// </summary>
        private void SetReaded()
        {
            using (FileStream fs = File.OpenWrite(FileInformation.FullName))
            {
                using (BinaryWriter binWriter = new BinaryWriter(fs))
                {
                    binWriter.Write(true);
                }
            }
        }
 
        /// <summary>
        /// Загрузить документ
        /// </summary>
        private FlowDocument LoadDocument()
        {
            using (FileStream fs = File.OpenRead(FileInformation.FullName))
            {
                using (BinaryReader binReader = new BinaryReader(fs))
                {
                    isReaded = binReader.ReadBoolean();
                    Date = DateTime.FromBinary(binReader.ReadInt64());
                    Title = binReader.ReadString();
                    return (FlowDocument)XamlReader.Parse(binReader.ReadString());
                }
            }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected void OnPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); //чтобы картинка в ListView обновилась
        }
    }
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.02.2011, 22:51

Открыть существующий FlowDocument в RichTextBox через TreeView
Добрый день! После дня Гугла, решения вопроса не нашел. Если кто знает....

Не срабатывает событие при клике на ссылку в RichTextBox или FlowDocument
Добрый день! Есть следующий код: &lt;Window...

COM объекты и их освобождение
Есть у меня программка, цель которой перебрать много документов путём их...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru