Распознавание голоса и речи на C#
UnmanagedCoder 05.05.2025
Интеграция голосового управления в приложения на C# стала намного доступнее благодаря развитию специализированных библиотек и API. При этом многие разработчики до сих пор считают голосовое управление. . .
Реализация своих итераторов в C++
NullReferenced 05.05.2025
Итераторы в C++ — это абстракция, которая связывает весь экосистему Стандартной Библиотеки Шаблонов (STL) в единое целое, позволяя алгоритмам работать с разнородными структурами данных без знания их. . .
Разработка собственного фреймворка для тестирования в C#
UnmanagedCoder 04.05.2025
C# довольно богат готовыми решениями – NUnit, xUnit, MSTest уже давно стали своеобразными динозаврами индустрии. Однако, как и любой динозавр, они не всегда могут протиснуться в узкие коридоры. . .
Распределенная трассировка в Java с помощью OpenTelemetry
Javaican 04.05.2025
Микросервисная архитектура стала краеугольным камнем современной разработки, но вместе с ней пришла и головная боль, знакомая многим — отслеживание прохождения запросов через лабиринт взаимосвязанных. . .
Шаблоны обнаружения сервисов в Kubernetes
Mr. Docker 04.05.2025
Современные Kubernetes-инфраструктуры сталкиваются с серьёзными вызовами. Развертывание в нескольких регионах и облаках одновременно, необходимость обеспечения низкой задержки для глобально. . .
Создаем SPA на C# и Blazor
stackOverflow 04.05.2025
Мир веб-разработки за последние десять лет претерпел коллосальные изменения. Переход от традиционных многостраничных сайтов к одностраничным приложениям (Single Page Applications, SPA) — это. . .
Реализация шаблонов проектирования GoF на C++
NullReferenced 04.05.2025
«Банда четырёх» (Gang of Four или GoF) — Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес — в 1994 году сформировали канон шаблонов, который выдержал проверку временем. И хотя C++ претерпел. . .
C# и сети: Сокеты, gRPC и SignalR
UnmanagedCoder 04.05.2025
Сетевые технологии не стоят на месте, а вместе с ними эволюционируют и инструменты разработки. В . NET появилось множество решений — от низкоуровневых сокетов, позволяющих управлять каждым байтом. . .
Создание микросервисов с Domain-Driven Design
ArchitectMsa 04.05.2025
Архитектура микросервисов за последние годы превратилась в мощный архитектурный подход, который позволяет разрабатывать гибкие, масштабируемые и устойчивые системы. А если добавить сюда ещё и. . .
Многопоточность в C++: Современные техники C++26
bytestream 04.05.2025
C++ долго жил по принципу «один поток — одна задача» — как старательный солдатик, выполняющий команды одну за другой. В то время, когда процессоры уже обзавелись несколькими ядрами, этот подход стал. . .
Had same issue in VS. I closed and restarted VS and no longer got the error.
Try adding the following references:
- PresentationCore
- PresentationFramework
- WindowsBase
With the ReferenceManager in your project.
The above references are the references used by wpf.
Tags:
Wpf
Xaml
Related
Содержание
- Приложение не поддерживается в проекте Windows Presentation Foundation (WPF)
- 2 ответа
- Похожие вопросы:
- WPF: Что делать, когда свойство не поддерживает привязку
- Введение
- Определяемся со способом реализации
- Пишем код
- Результат
- Заключение
- Подводные камни WPF
- Засорение памяти экземплярами ResourceDictionary
- Утечки памяти
- Утечки на событиях
- Утечки при байндинге
- Наследование визуальных компонентов и стили
- Ошибки байндинга
- Стандартные средства валидации
- Неправильное использование события PropertyChanged
- Избыточное использование Dispatcher
- Модальные диалоги
- Анализ производительности отображения
- И еще немного о INotifyPropertyChanged
- Вместо послесловия
Приложение не поддерживается в проекте Windows Presentation Foundation (WPF)
Я только что создал новый проект WPF в blend, нажал его на git, добавил драйверы mqsql, сервис rest и nfc sdk, и вдруг blend говорит мне, что приложение не поддерживается. Ошибка приводит меня к App.xaml, который полностью неотредактирован и выглядит следующим образом:
Та же ошибка относится практически к любому тегу, такому как Style, Setter, ControlTemplate, Canvas, Path. ничто не поддерживается. сравнивая оба файла xaml и c# с другим проектом, который я только что закончил, который работает просто отлично, нет никакой разницы (кроме пространства имен и пути, естественно)
Я совершенно ошарашен
2 ответа
Сразу же после добавления совершенно нового, нетронутого окна WPF в мой проект IronPython 2.7 в VS2013 (с инструментами Python для VS 2.0.11016) он сообщает мне «Invalid Markup» в окне дизайна, и список ошибок показывает: Окно не поддерживается в проекте Windows Presentation Foundation.
Была такая же проблема в VS году. Я закрыл и перезапустил VS и больше не получал ошибки.
Попробуйте добавить следующие ссылки:
С ReferenceManager в вашем проекте. Приведенные выше ссылки являются ссылками, используемыми wpf.
Похожие вопросы:
я читал о window presentation foundation и получил книгу windows презентация фонда развязана. Но, к моему удивлению, код был в c#. Вопрос : Доступно ли wpf разработчикам c++? если не почему. Спасибо
Сразу же после добавления совершенно нового, нетронутого окна WPF в мой проект IronPython 2.7 в VS2013 (с инструментами Python для VS 2.0.11016) он сообщает мне «Invalid Markup» в окне.
Я пытаюсь запустить код из вопроса понимание реализации ICommand без MVVM в VS2012 (окно 7), но получаю ошибки: AppCommand are not supported in a Windows Presentation Foundation (WPF) project Ну.
Я создал проект WPF в VS 2013 году. После обновления до VS 2015 эта ошибка появилась в конструкторе на типах, полученных из Blend SDK: тип из assembly построен с более старой версией blend sdk и не.
Почему я должен получить BoolToRowHeightConverter не поддерживается в проекте Windows Presentation Foundation(WPF) ошибка в xaml? Я использовал конвертер для преобразования rowheight В * и Auto в.
Почему я получаю следующую ошибку: Int16 is not supported in a windows presentation foundation project wpf. Я читал следующий текст MSDN: MSDN преобразование текста в примитивы Ниже приведен мой.
Источник
WPF: Что делать, когда свойство не поддерживает привязку
Введение
WPF — замечательная технология, которую, не смотря на все ее недостатки, очень люблю. Тем не менее, часто приходится писать не разметку, а код, который помогает первой работать как надо. Хотелось бы этого избегать и писать чистый XAML, но до сих пор ни одно мое приложение сложнее простого не обходилось без различных хелперов (классов-помощников), написанных на C#. К счастью, есть распространенные случаи, где можно одним хелпером решить сразу группу проблем.
Речь ниже пойдет о привязке в обычных свойствах визуальных элементов, которые не являются свойствами зависимостей (dependency properties). Штатными средствами WPF этого сделать не получится. Ко всему прочему, мы не можем узнать об изменениях такого свойства, кроме как подписавшись на специальное событие, что противоречит шаблону MVVM. Такие события для каждого свойства могут быть свои. Самый распространенный пример — это PasswordBox и его свойство Password. Так у нас сделать не получится:
Не будем вдаваться в подробности, зачем разработчики PasswordBox не разрешили привязываться к свойству пароля. Подумаем, что тут можно сделать.
Если вам не хочется читать мои рассуждения, то в конце статьи опубликован финальный код и ссылка на Github.
Определяемся со способом реализации
Есть разные способы достичь желаемого. Остановимся на стандартном для таких случаев механизме — поведениях.
Пишем код
Добавим ссылку на сборку System.Windows.Interactivity.dll. Это часть SDK редактора Expression Blend и находится в разделе «Расширения» окна выбора сборок Visual Studio.
Создадим класс, наследуемый от Behavior :
Тип генерика DependencyObject выбран как наиболее общий. Ведь мы пишем универсальный класс, подходящий для любого элемента, а не только PasswordBox.
Теперь, когда у нас есть все входные данные, приступим к их обработке в переопределенном методе OnAttached(). Он вызывается при присоединении поведения к визуальному элементу. К последнему можно обращаться через свойство класса AssociatedObject. В противовес, при отсоединении вызывается OnDetaching().
Нам нужны объекты для работы со свойством визуального элемента и событием через рефлексию. Ниже показано их получение и подписывание на событие, уведомляющее об изменениях свойства визуального элемента.
Далее в примерах я опустил различные проверки на null, чтобы не засорять внимание. В итоговом варианте класса они присутствуют.
В коде выше имеется метод CreateDelegateForEvent(). Он компилирует объект делегата для указанного события во время выполнения. Ведь заранее мы не знаем сигнатуру обработчика события. При компиляции в делегат помещается вызов метода action, которым в нашем случае является EventFired(). В нем мы будем выполнять нужные нам действия для обновления значения источника данных.
Эта операция довольно ресурсоемка, но выполняется лишь раз, при подключении поведения. Ее можно оптимизировать жертвуя гибкостью, предположив, что события могут быть только RoutedEvent. Тогда, вместо дорогой компиляции, достаточно подписаться на событие с указанием обработчика EventFired(), предварительно изменив ему сигнатуру на совместимую с RoutedEventHandler. Но оставим здесь оригинальный вариант. Преждевременная оптимизация — зло.
Метод EventFired() предельно прост, он записывает новое значение в источник данных:
Осталась самая малость — менять значение свойства визуального элемента при изменении источника данных. Для этого подойдет переопределяемый метод OnPropertyChanged(), который сообщает об изменениях свойств зависимостей класса. Так как при изменении источника данных меняется и свойство Binding, то нам достаточно отслеживать его новые значения.
Все, вроде бы, прекрасно. Мы задаем новое значение свойства визуального элемента и… получаем StackOverflowException.
Проблема в том, что при изменении свойства автоматом вызывается уведомляющее событие, на которое мы подписаны. В событии изменяется значение источника, а при изменении источника меняется свойство Binding, что приводит нас снова в метод OnPropertyChanged(). Рекурсия.
Самым простым решением будет добавление сравнения старого и нового значения свойства:
Здесь делаем допущение, что Equals() у типа реализован как надо и не будет вечно возвращать false.
Результат
В данном случае TextBox и PasswordBox будут синхронно менять значения.
Заключение
Мы добились работы привязки для свойства визуального элемента, которое изначально ее не поддерживало. Привязка работает в оба направления и можно использовать класс поведения для любого элемента, не беспокоясь о различиях в именах свойств и событий.
Заранее извиняюсь за неточности в тексте, моя первая статья.
Как и обещал, финальный код:
Источник
Подводные камни WPF
Засорение памяти экземплярами ResourceDictionary
Зачастую разработчики явно включают необходимые словари ресурсов прямо в XAML разметке пользовательских элементов управления вот таким образом:
На первый взгляд, в таком подходе нет никакой проблемы — просто для элемента управления указываем минимально необходимый набор стилей. Предположим, в нашем приложении SomeControl существует в 10 экземплярах на одном из окон. Проблема заключается в том, что при создании каждого из этих экземпляров, указанный словарь будет заново вычитываться, обрабатываться и храниться отдельной копией в памяти. Чем больше подключаемые словари, чем больше экземпляров — тем больше уходит времени на инициализацию содержащего их представления и тем больше памяти расходуется впустую. Мне на практике приходилось иметь дело с приложением, в котором перерасход памяти из-за лишних ResourceDictionary был порядка 200 мегабайт.
Мне известно два варианта решения этой проблемы. Первый — подключать все необходимые словари стилей только в App.xaml и больше нигде. Вполне может подойти для небольших приложений, но для сложных проектов может быть неприемлем. Второй — вместо стандартного ResourceDictionary использовать его наследника, который кеширует словари таким образом, что каждый из них хранится в памяти только в одном экземпляре. К сожалению, WPF по какой-то причине не предоставляет такую возможность «из коробки», но ее легко реализовать самостоятельно. Одно из наиболее полных решений можно найти в последнем ответе здесь — http://stackoverflow.com/questions/6857355/memory-leak-when-using-sharedresourcedictionary.
Утечки памяти
Утечки на событиях
Даже в среде с автоматической сборкой мусора можно легко получить утечки памяти. Наиболее частая причина утечек, и не только в WPF проектах — подписка на события без последующего удаления обработчика. Хоть это и не проблема самой технологии, на ней стоит остановиться поподробнее, так как в WPF проектах события используются часто и вероятность появления ошибки высока.
Например, в приложении есть список объектов, свойства которых можно изменять в окне редактирования. Для реализации этого окна понадобилось устанавливать IsModified в true внутри его модели представления при изменении любого свойства редактируемого объекта.
Предположим, модель представления для редактирования реализована так:
Здесь конструктор устанавливает «сильную» ссылку между бизнес-сущностью и моделью представления редактора. Если создавать экземпляр EntityEditorViewModel при каждом показе окна, то такие объекты будут накапливаться в памяти и удалятся только в том случае, если ссылающаяся на них бизнес-сущность станет «мусором».
Один из вариантов решения проблемы — предусмотреть удаление обработчика. Например, реализовать IDisposable и в методе Dispose() «отписываться» от события. Но тут сразу стоит сказать, что обработчики, заданные лямбда-выражениями как в примере, не могут быть удалены простым способом, т.е. вот такое не сработает:
Для правильного решения задачи нужно объявить отдельный метод, поместить в него установку IsModified и использовать в качестве обработчика, как всегда и делалось до появления лямбда-выражений в C#.
Но подход с явным удалением не гарантирует отсутствие утечек памяти — можно банально забыть позвать Dispose(). Помимо этого, может быть очень проблематично определить тот момент, когда нужно его вызвать. В качестве альтернативы можно рассмотреть более громоздкий, но действенный подход — Weak Events. Общая идея их реализации в том, что между источником события и подписчиком устанавливается «слабая» ссылка, и подписчик может быть автоматически удален, когда на него больше не станет «сильных» ссылок.
Объяснение реализации паттерна Weak Events выходит за рамки этот статьи, поэтому просто укажу ссылку, где эта тема рассмотрена очень подробно: http://www.codeproject.com/Articles/29922/Weak-Events-in-C.
Утечки при байндинге
Помимо потенциальной проблемы, описанной выше, в WPF есть как минимум два типа утечек, которые специфичны именно для этой технологии.
Предположим, у нас есть простой объект:
И мы привязываемся к этому свойству из какого-либо элемента управления:
Если свойство, к которому идет привязка, не является DependencyProperty, либо объект, содержащий его, не реализует INotifyPropertyChanged — механизм байндинга использует событие ValueChanged класса System.ComponentModel.PropertyDescriptor для отслеживания изменений. Проблема здесь в том, что фреймворк держит у себя ссылку на экземпляр PropertyDescriptor, который в свою очередь ссылается на исходный объект, и неясно, когда этот экземпляр можно будет удалить. Следует отметить, что в случае с OneTime байндингом проблема не актуальна, так как не нужно отслеживать изменения.
Информация об этой проблеме есть и в Microsoft Knowledge Base: https://support.microsoft.com/en-us/kb/938416, но в ней указано одно дополнительное условие возникновения утечки. Если применить его к предыдущему примеру, то получим, что экземпляр SomeModelEntity должен прямо или косвенно ссылаться на TextBox, чтобы произошла утечка. С одной стороны, такое условие довольно редко выполняется на практике, но в реальности лучше всегда придерживаться более «чистого» подхода — либо явно указывать OneTime режим байндинга, если не нужно следить за изменениями, либо реализовывать INotifyPropertyChanged на объекте-источнике, либо делать свойство DependencyProperty (имеет смысл для свойств визуальных компонентов).
Другая возможная проблема при установке байндингов — привязка к коллекциям, которые не реализуют интерфейс INotifyCollectionChanged. Механизм возникновения утечек в этом случае очень похож на предыдущий. Способ борьбы очевиден — нужно либо явно указывать OneTime режим привязки, либо использовать коллекции, реализующие INotifyCollectionChanged — например, ObservableCollection.
Наследование визуальных компонентов и стили
Иногда возникает надобность в наследовании стандартных элементов управления для расширения их функциональности, изменения поведения. На первый взгляд, это элементарно:
Но если в приложении используются стили элементов, отличные от стилей по умолчанию, проблема при использовании такого наследника будет заметна сразу. Следующий фрагмент скриншота показывает разницу в отображении базового элемента управления и производного при включенной теме PresentationFramework.Aero.
Самый простой способ это исправить — в XAML файле после включения ресурсов темы определить стиль для производного элемента, как унаследованного от базового. Это легко осуществляется с помощью атрибута BasedOn:
Но получается, что при использовании производного элемента управления нужно всегда помнить и о добавлении стиля в ресурсы. Или же сделать файл с этим производным стилем и подключать его каждый раз, когда нужно использовать новый элемент.
Есть один способ обойтись без изменений в XAML — в конструкторе производного элемента явно устанавливать ему стиль, взятый с базового:
Таким образом, если не нужно добавлять никаких изменений в базовый стиль, этот способ будет наиболее оптимальным. В противном случае лучше воспользоваться предыдущим вариантом.
Ошибки байндинга
Декларативное связывание элементов управления с полями модели, конечно же, имеет свои преимущества, но за его целостностью не так уж просто следить. Если по какой-то причине свойство, указанное в байндинге, не найдено — ошибка будет написана в лог отладки… И всё. По умолчанию пользователь не увидит никаких сообщений, при запуске без отладки ни в каких логах этих ошибок не будет.
Чтобы сделать такие ошибки более заметными для разработчика, можно написать специальный Trace Listener, который будет выводить их в виде сообщений:
И затем активировать его при старте приложения:
После этих изменений каждая ошибка байндинга будет выводиться в виде диалогового сообщения, но только при запуске с отладкой, поэтому имеет смысл воспользоваться условной компиляцией, чтобы в релизных версиях обработчик не регистрировался.
Стандартные средства валидации
В WPF существует несколько способов валидации данных.
ValidationRule — наследуя этот класс можно создавать специализированные правила валидации, которые затем привязываются к полям в XAML разметке. Из «условных» плюсов — не требуются изменения классов модели для выполнения валидации, хотя в некоторых случаях это может быть не самым оптимальным вариантом. Но при этом есть значительный недостаток — ValidationRule не наследует DependencyObject, соответственно в наследниках нет возможности создавать свойства, на которые в последствии можно будет байндиться. Это означает, что нет простого очевидного способа производить валидацию свойств в связке друг с другом — например, если значение одного не может быть больше значения другого. Валидационное правило, реализованное таким способом, может иметь дело только с текущим значением поля и фиксированными значениями свойств, которые были указаны при создании экземпляра этого правила.
IDataErrorInfo, INotifyDataErrorInfo — реализуя эти интерфейсы в классах моделей представления можно легко осуществлять валидацию как отдельных свойств, так и нескольких свойств в связке друг с другом. Обычно для уменьшения количества кода один из этих интерфейсов реализуют в базовом классе моделей и предоставляют средства лаконичного описания правил в наследниках. Например, через регистрацию правил в статическом конструкторе для каждого из типов:
Или через атрибуты:
Но и подход с использованием DataErrorInfo интерфейсов не покрывает все валидационные задачи — в случаях, когда для проверки правила нужно иметь доступ к объектам за пределами валидируемой сущности, начинают возникать проблемы. Например, проверка на уникальность требует доступа к полной коллекции объектов, а это означает что каждый элемент такой коллекции должен иметь ссылку на нее, что сильно усложняет работу с объектом.
К сожалению, стандартных средств, позволяющих легко обойти эту проблему, в WPF нет, и приходится писать что-то свое. В самом простом случае, если перед сохранением записи должна быть проверена ее уникальность, это можно сделать явно в коде перед вызовом сохранения и показать сообщение в случае ошибки.
Такой подход на самом деле тоже можно обобщить. Воспользуемся упомянутой выше идеей с регистрацией валидаторов в статическом конструкторе. Вот пример базового класса:
А также пример использования:
Таким образом, все валидационные правила находятся внутри самой сущности. Те из них, которые не требуют «внешних» объектов, используются в реализации IDataErrorInfo из базового класса. Для проверки остальных достаточно позвать функцию Validate в нужном месте и использовать результат для принятия решений о дальнейших действиях.
Неправильное использование события PropertyChanged
Мне довольно часто приходилось встречать код подобного вида в WPF проектах:
Причем во многих случаях это был обработчик собственных событий, т.е. «слушал» изменения свойств того же класса, где и был объявлен.
В таком подходе есть несколько серьезных недостатков, которые по итогу приводят к очень тяжелому в плане поддержки и расширения коду. Некоторые из них очевидны: например, при переименовании свойств можно забыть изменить константы в условиях, но это мелкий и легко решаемый недостаток. Гораздо более серьезная проблема в том, что при таком подходе бывает практически невозможно отследить все сценарии, при которых выполняется тот или иной кусок логики.
Можно сформулировать следующий критерий для самопроверки, правильно ли используется обработчик события PropertyChanged: если алгоритм внутри обработчика не зависит от конкретных названий свойств, то все в порядке. В противном случае нужно искать более удачное решение. Примером правильного применения может быть, например, установка свойства IsModified в true при изменении какого-либо свойства модели представления.
Избыточное использование Dispatcher
Неоднократно встречал в WPF проектах принудительное выполнение операций на UI потоке даже в тех случаях, когда это не нужно. Для того, чтобы описать масштаб проблемы, приведу пару цифр, полученных с помощью простых тестов на ноутбуке c процессором Core i7-3630QM 2.4GHz:
Чтобы уменьшить вред для производительности, достаточно придерживаться простых правил:
Модальные диалоги
Использование стандартных модальных сообщений (MessageBox) в WPF проектах не приветствуется, так как кастомизировать их внешний вид в соответствии с визуальными стилями приложения попросту невозможно. Вместо стандартных сообщений приходится писать свои реализации, которые можно условно разделить на два типа:
Второй вариант обычно вызывает множество проблем в реализации, которые вызваны тем, что показ такого окна не может быть синхронным. То есть, нельзя будет написать как с привычными сообщениями:
и ожидать что на основном потоке больше ничего не может произойти, пока пользователь не ответит на вопрос.
Рассмотрим одну из наиболее простых реализаций «эмулированного» диалога.
В первую очередь объявим интерфейс менеджера диалогового окна, через который модель представления будет показывать диалоги. Для начала не будем учитывать возможность получать «ответ» от окна — просто покажем диалог с кнопкой «Закрыть».
Далее реализуем элемент управления, который будет «привязываться» к менеджеру и показывать окно поверх остальных элементов, когда это необходимо:
Опять же, для упрощения, этот контрол рассчитан на то, что в модели представления есть экземпляр реализации IModalDialogHelper в свойстве DialogHelper. В более универсальном решении должна быть возможность подставлять любое свойство.
Я не буду здесь приводить пример простейшей реализации IModalDialogHelper, так как она очевидна: методы Show() и Close() устанавливают соответствующим образом IsVisible, команда CloseCommand просто вызывает метод Close(). Show() еще устанавливает свойство Text.
Вроде бы все просто: вызываем метод Show() с нужным текстом сообщения, он делает видимым панель с сообщением и кнопкой, последующее нажатие на кнопку Close устанавливает IsVisible в исходное значение и «диалог» пропадет с экрана. Но тут уже есть первая проблема — последовательный показ нескольких сообщений приводит к тому, что пользователь видит только последнее, так как метод Show() не ожидает закрытия предыдущего диалога.
Для решения этой проблемы немного изменим прототип метода Show:
Возможность ожидать завершения этого метода через await дает стразу несколько преимуществ:
Основная идея этого решения заключается в том, что для каждого вызова Show создается экземпляр TaskCompletionSource. Ожидание задачи, созданной внутри него будет продолжаться до тех пор, пока не указан результат через вызов SetResult. Show до показа своего сообщения ждет все задачи, которые уже есть в очереди, после показа — ждет свою собственную, а Close устанавливает результат выполнения текущей задачи, тем самым завершая ее.
И следует сказать еще пару слов об использовании «новых» диалогов в обработчиках событий типа CancelEventHandler. Подтверждение действий в таких событиях тоже нужно будет реализовывать немного не так как раньше.
Проблема в том, что e.Cancel всегда будет true для кода, вызвавшего Window_Closing, так как await не останавливает выполнение потока, а создает возможность «вернуться» в нужное место в методе после завершения асинхронной задачи. Для вызвавшего кода, Windows_Closing завершится сразу после установки e.Cancel в true.
Правильное решение заключается в том, что тело условия должно оперировать уже не e.Cancel, а явно вызывать «отмененное» действие таким образом, чтобы оно гарантированно выполнилось без дополнительных запросов, минуя повторный вызов этого обработчика. В случае закрытия главного окна программы, например, это может быть явный вызов завершения всего приложения.
Анализ производительности отображения
Многие разработчики знают, что такое «профайлер» и знают, какие есть средства для анализа производительности приложения и анализа потребления памяти. Но в WPF приложениях часть нагрузки на процессор исходит, например, из механизма обработки XAML разметки – парсинг, разметка, рисование. «Стандартными» профайлерами непросто определить, на какую именно активность, связанную с XAML, тратятся ресурсы.
Не буду подробно останавливаться на возможностях существующих инструментальных средств, просто перечислю ссылки на информацию о них. Разобраться с тем, как ими пользоваться, не составит труда любому разработчику.
И еще немного о INotifyPropertyChanged
Одна из самых популярных тем споров в рамках технологии WPF — как наиболее рационально реализовывать INotifyPropertyChanged. Самый лаконичный вариант — использовать АОП, как я уже описывал в одном из примеров в статье об Aspect Injector. Но не всем этот подход нравится, и в качестве альтернативы можно использовать сниппеты. Но тут возникает вопрос о наиболее оптимальном содержимом сниппета. Сперва приведу примеры не самых удачных вариантов.
В данном случае имя свойства указано константой, и не важно — будет оно в именованной константе или, как в примере, «захардкоджено» прямо в вызове метода оповещения — проблема остается той же: при переименовании самого свойства существует вероятность оставить старое значение константы. Эту проблему многие решают следующим изменением метода NotifyPropertyChanged:
В этом случае вместо названия можно указать лямбда-выражение, возвращающее нужное свойство:
К сожалению, этот вариант тоже имеет недостатки — вызов такого метода всегда связан с Reflection, что по итогу в сотни раз медленнее вызова предыдущего варианта NotifyPropertyChanged. В случае приложений для мобильных устройств это может быть критичным.
Если параметр, помеченный этим атрибутом, не указан явно, компилятор подставит в него имя члена класса, вызывающего метод. Таким образом вызов NotifyPropertyChanged() из примера выше равнозначен NotifyPropertyChanged(“Name”). Но что делать, если нужно сообщить об изменении какого-либо свойства «снаружи», не из его сеттера?
Например, у нас есть «калькулируемое» свойство:
При добавлении, удалении или изменении элементов коллекции items нам нужно сообщать об изменении TotalPrice, чтобы интерфейс пользователя всегда отображал его актуальное значение. Учитывая недостатки первых двух решений, приведенных выше, можно сделать следующий ход — все-таки использовать Reflection для получения имени свойства из лямбда-выражения, но сохранять его в статической переменной. Таким образом для каждого отдельно взятого свойства «тяжелая» операция будет выполняться только один раз.
Саму статическую функию GetPropertyName можно положить и в базовый класс для всех «notifiable» сущностей — это не принципиально. Проверка на UnaryExpression нужна, чтобы функция нормально обрабатывала свойства значимых типов, т.к. компилятор добавляет операцию боксинга, чтобы привести указанное свойство к object.
Если ваш проект уже использует C# 6.0, то ту же задачу получения имени другого свойства можно решить намного проще — с помощью ключевого слова nameof. Надобности в статической переменной, которая запоминает имя, уже не будет.
В качестве итога можно сказать, что если использование АОП для INotifyPropertyChanged по каким-либо причинам не устраивает, то можно воспользоваться сниппетами следующего содержания:
Вместо послесловия
WPF — неплохая технология, которую Microsoft по-прежнему позиционирует как основной фреймворк для разработки «настольных» приложений. К сожалению, при написании программ сложнее «калькулятора» обнаруживается ряд проблем, не заметных с первого взгляда, но все они решаемы. Согласно недавним заявлениям Microsoft, они инвестируют в развитие технологии, и в новой версии уже есть много улучшений. В первую очередь они относятся к инструментальным средствам и производительности. Хочется надеяться, что в будущем новые возможности будут добавлены не только в инструментальные средства, но и в сам фреймворк, облегчая работу программиста и избавляя от «хаков» и «велосипедов», которые приходится делать сейчас.
UPD: изменил второе решение в разделе «Наследование визуальных компонентов и стили» на более оптимальное из комментариев и добавил в раздел о INotifyPropertyChanged решение с nameof() для C# 6.0
UPD2: изменил пример реализации хелпера для модального диалога на более лаконичный с использованием TaskCompletionSource.
Источник
У меня неприятное время с Blend reporting «окно не поддерживается в проекте Windows Presentation Foundation (WPF).»из-за несъемных конфигураций, но не могу понять, как из него выбраться.
Я разработал это, вероятно, из-за моей попытки иметь одно решение с конфигурациями x86 и x64. Нет никакого способа сказать Blend 2, который является активным Настройки Решение и Active решение Платформа.
Я думаю, что это немного слабость в системе конфигурации, или, может быть, так, как я все настроил, но у меня есть Debug64 и Debug конфигурации один из каждого используется с платформа x86 и x64.
Я также думаю, что это простая проблема сортировки — x64 приходит до x86, а Debug приходит до Debug64, поэтому Blend заканчивается нестроеной конфигурацией отладки с x64.
когда я выбираю сочетание Debug и x64 в VS, его редактор XAML также не может загрузить.
решение является умеренно сложным — есть чистый Win32 DLL, проект модели C++/CLI и две другие сборки WPF, используемые основным проектом WPF.
обновление
Я вырвал всю конфигурацию x64 из своего решения и перестроил все без эффекта.
затем я удалил Blend 2 и установил Blend 3 — ему тоже не нравится.
редактор Visual Studio XAML по-прежнему очень счастлив, как и программа построения и запуска.
(Эхо сдавленного крика разочарования из страны Оз)
4 ответов
Blend требует, чтобы решение также имело платформу AnyCPU в configuration manager.
Любые проекты C++ (включая C++/CLI) в решении загружаться не будут.
У меня есть платформы AnyCPU +x86 +x64 в моих решениях, AnyCPU не строит не проекты C#.
поместите окна / элементы управления в библиотеки DLL AnyCPU C#, чтобы их можно было редактировать в blend.
(Не ссылайтесь на проекты x86/x64 из них.)
установите exe как x86 и x64 только (нет AnyCPU) — не будет работать в blend (нет AnyCPU),
но решение все равно будет строить.
есть также несколько других причин, по которым это может произойти:
1) отсутствующие ссылки. Добавьте ссылку на PresentationCore, PresentationFramework и WindowsBase
Он также может искать .DLL с неправильной платформы. Я просто решил свою проблему, сделав следующее изменение:
в рамках .файл csproj в вопросе, измените эту строку
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
до
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
Я столкнулся с этой проблемой с VS2010 и Blend4. Внезапно мой проект перестал быть смешанным.
проблема заключалась в том, что разработчик в нашей команде настраивал пользовательские конфигурации сборки. Когда он это сделал, он удалил Debug. Как только я добавил Debug обратно в конфигурацию сборки, смесь снова была счастлива.
со своей стороны, я решил проблему следующим образом:
- трюк AnyCPU (но недостаточно…)
- выгрузите проект, отредактируйте файл проекта, посмотрите ссылки на 4.0 framework и измените их на 4.5 (целевая и миниальная Требуемая версия).
перестроить решение, затем смешать предварительный просмотр для WPF 4.5 остановился, чтобы показать ошибку messsage (окно не поддерживается…).
спасибо всем, что поставили меня на трек !
На чтение5 мин
Опубликовано
Обновлено
Windows Presentation Foundation (WPF) Autocad – это технология, которая предоставляет возможность разработки и использования графических интерфейсов в операционных системах Windows.
Однако, при использовании Autocad на компьютере с установленной операционной системой, устаревшей или несовместимой с требованиями WPF, возникает ошибка «неподдерживаемая версия Windows Presentation Foundation Autocad».
Эта ошибка указывает на то, что текущая версия операционной системы не поддерживает требования WPF Autocad и не может обеспечить полноценную работу данного приложения.
Для решения данной проблемы рекомендуется обновить операционную систему до поддерживаемой версии или проверить наличие последних обновлений и патчей, которые могут исправить данную ошибку. Также необходимо убедиться, что установленная версия Autocad совместима с текущей операционной системой.
В случае, если обновление операционной системы или патчи не решают проблему, возможно, стоит обратиться к службе поддержки Autocad для получения дополнительной информации и помощи.
Что делать при ошибке «неподдерживаемая версия Windows Presentation Foundation Autocad»?
Чтобы исправить эту ошибку, вы можете попробовать следующие шаги:
- Обновите версию Autocad. Проверьте, есть ли доступные обновления или патчи для вашей версии Autocad. Установите все доступные обновления для устранения возможных проблем совместимости.
- Установите последнюю версию WPF. Проверьте, что у вас установлена последняя версия WPF, совместимая с вашей версией Autocad. Вы можете загрузить и установить WPF из официального сайта Microsoft.
- Проверьте системные требования. Убедитесь, что ваш компьютер соответствует системным требованиям Autocad и WPF. Если ваш компьютер не соответствует минимальным требованиям, возможно, вам нужно обновить аппаратное обеспечение или операционную систему.
- Обратитесь в службу поддержки. Если вы все еще сталкиваетесь с ошибкой «неподдерживаемая версия Windows Presentation Foundation Autocad», рекомендуется обратиться в службу поддержки Autocad или Microsoft для получения дальнейшей помощи и решения проблемы.
Внимание! Перед выполнением любых действий рекомендуется создать резервную копию данных и сохранить все открытые файлы, чтобы избежать потери информации.
В случае возникновения ошибки «неподдерживаемая версия Windows Presentation Foundation Autocad» важно принять соответствующие меры для ее устранения и продолжения работы с программой Autocad.
Понимание ошибки
Ошибка «неподдерживаемая версия Windows Presentation Foundation Autocad» указывает на проблему с совместимостью версий программного обеспечения Autocad и Windows Presentation Foundation (WPF).
Autocad — это программное обеспечение, используемое для 2D и 3D проектирования и черчения. WPF — это технология, разработанная компанией Microsoft, для создания графических пользовательских интерфейсов в Windows-приложениях. Ошибка возникает, если установленная версия Autocad несовместима с установленной версией WPF на вашем компьютере.
Чтобы решить эту проблему, вам необходимо проверить совместимость версий Autocad и WPF.
- Убедитесь, что у вас установлена поддерживаемая версия WPF. Проверьте требования к системе Autocad и убедитесь, что установленная версия WPF соответствует этим требованиям. Если ваша текущая версия WPF несовместима, обновите ее до поддерживаемой версии.
- Убедитесь, что у вас установлена правильная версия Autocad. Проверьте требования к системе Autocad и убедитесь, что установленная версия соответствует этим требованиям. Если ваша текущая версия Autocad несовместима, обновите ее до поддерживаемой версии или установите совместимую версию.
- Если у вас установлена правильная версия Autocad и WPF, но ошибка по-прежнему возникает, проверьте, нет ли драйверов или обновлений для видеокарты, которые могут повлиять на совместимость Autocad и WPF. Обновите драйверы видеокарты до последней версии.
Если вы продолжаете сталкиваться с ошибкой «неподдерживаемая версия Windows Presentation Foundation Autocad», свяжитесь с технической поддержкой Autocad или обратитесь к разработчикам программного обеспечения для получения дополнительной помощи и рекомендаций.
Проверка версии Windows Presentation Foundation
Однако, некоторые версии Windows Presentation Foundation могут быть неподдерживаемыми на некоторых устройствах или операционных системах. Поэтому, перед запуском приложения, необходимо проверить совместимость версии Windows Presentation Foundation с установленной операционной системой.
Для проверки версии Windows Presentation Foundation на данный момент можно выполнить следующие шаги:
- Откройте командную строку, нажав на кнопку «Пуск» и введя в поисковой строке «cmd».
- Нажмите правой кнопкой мыши на найденный результат и выберите «Запустить от имени администратора».
- В открывшемся окне командной строки введите команду «reg query «HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full» /v Release».
- Нажмите клавишу «Enter» для выполнения команды.
- После выполнения команды будет выведена информация о текущей установленной версии Windows Presentation Foundation.
После проверки версии Windows Presentation Foundation можно убедиться в ее совместимости с операционной системой и принять необходимые меры для исправления проблемы, если она возникла.
Обновление Windows Presentation Foundation
Для решения проблем, связанных с ошибкой «неподдерживаемая версия Windows Presentation Foundation», рекомендуется выполнить обновление самой платформы WPF. Обновление позволит исправить ошибки, улучшить производительность и обеспечит поддержку новых функций и возможностей.
Чтобы обновить Windows Presentation Foundation, следуйте инструкциям ниже:
- Перейдите на официальный сайт Microsoft и найдите раздел загрузок.
- Найдите и загрузите последнюю доступную версию Windows Presentation Foundation.
- Запустите загруженный файл и следуйте инструкциям мастера установки.
- После завершения установки перезапустите компьютер.
После обновления Windows Presentation Foundation, проверьте работу приложения, в котором ранее возникала ошибка «неподдерживаемая версия Windows Presentation Foundation Autocad». Если ошибка продолжает возникать, рекомендуется обратиться за поддержкой к разработчикам программы или в форумы поддержки Microsoft.
Обновление Windows Presentation Foundation является важным шагом для обеспечения правильной работы приложений, использующих эту технологию, и обновление позволит исправить ошибки, повысить безопасность и обеспечить совместимость с новыми версиями операционной системы Windows.
Обратиться к разработчикам
Если вы столкнулись с ошибкой «Неподдерживаемая версия Windows Presentation Foundation Autocad» и не можете продолжить работу в программе, рекомендуется обратиться к разработчикам для получения помощи и поддержки. В данном случае можно предпринять следующие действия:
- Проверьте, имеется ли у вас последняя версия программы Autocad, которая поддерживает Windows Presentation Foundation.
- Посетите официальный сайт Autocad и просмотрите раздел «Поддержка», возможно, там есть решение вашей проблемы или инструкция по устранению ошибки.
- Воспользуйтесь форумами и онлайн-сообществами пользователей Autocad, чтобы обратиться за помощью. Там вы можете задать свой вопрос или описать проблему, возможно, кто-то уже сталкивался с подобной ситуацией и сможет помочь вам.
- Если все предыдущие шаги не привели к решению проблемы, обратитесь в техническую поддержку Autocad. На официальном сайте обычно указаны контакты и способы связи с техподдержкой.
Не стесняйтесь обращаться за помощью, ведь разработчики программы Autocad лучше всех знают свой продукт и смогут дать вам наилучшие рекомендации. Удачи в решении проблемы!