Есть ли в WPF способ объявить тип DataContext предка?

В пользовательском элементе управления я использую RelativeSource для привязки к команде DataContext окна хостинга. Я использовал d:DataContext, чтобы указать тип DataContext как в пользовательском элементе управления, так и в окне хостинга.

В привязке команд я мог бы указать тип окна хостинга, используя AncerstorType, но не вижу способа указать тип его DataContext. Было бы неплохо иметь предупреждение во время разработки на случай, если свойство этого DataContext введено с ошибкой или не существует, а также убрать волнистые синие подчеркивания.

DataContext родительского окна должен быть унаследован UserControl, что происходит автоматически, если вы явно не установите для DataContext UserControl что-то другое. Явная установка DataContext пользовательского элемента управления (в его XAML или коде) является распространенной ошибкой программирования, поскольку она нарушает принцип работы стандартной привязки данных.

Clemens 14.06.2024 19:03

Добавлю к комментарию Клеменса: это означает, что вам нужно разрабатывать управляющие коды таким образом, чтобы они были полностью независимыми от DataContext. Это достигается путем введения свойства зависимости для каждого необходимого вам внешнего данных. Это был клиент вашего элемента управления, который мог использовать любой тип DataContex, который он хочет. Ему нужно только связать его свойства со свойствами элементов управления, чтобы предоставить данные. Точно так же вы привязываете коллекцию к свойству ItemsControl ItemsSource или строку к TextBloxk.Text. Эти элементы управления допускают повторное использование, поскольку они не знают своего DataContext.

BionicCode 14.06.2024 20:46

Таким образом, решение вашей проблемы состоит в том, чтобы правильно спроектировать элемент управления, как описано.

BionicCode 14.06.2024 20:46

Извините, но я не понимаю, почему переопределение DataContext является ошибкой программирования, если только я не злоупотребляю UserControl. Мне нравится проектировать UserControl — это представление, а связанная с ним модель представления, которая управляет взаимодействиями. Я установил DataContext пользовательского элемента управления (представления) в ViewModel, который им управляет. Я рассматриваю это как чистое разделение. Это неправильно? Если да, то почему?

PatriceBG 14.06.2024 21:17

«В пользовательском элементе управления я использую RelativeSource для привязки к команде DataContext окна хостинга» — это неправильный подход. Пользовательский элемент управления не должен делать предположений относительно хост-окна или его контекста данных. вместо этого вы можете объявить DP типа ICommand в пользовательском элементе управления и привязать это свойство к экземпляру в окне.

ASh 14.06.2024 21:31

@PatriceBG Вы можете провести небольшое исследование StackOverflow о UserControls (или любых других элементах управления) с моделями частного представления, например. stackoverflow.com/questions/1939345/…. Логика управления обычно находится в коде элемента управления, а не в модели частного представления. Если вы по-прежнему хотите разделить логику управления в модель частного представления, не задавайте DataContext пользовательского элемента управления, а просто задайте контекст элемента верхнего уровня в его XAML. Таким образом, стандартное наследование значения свойства DataContext по-прежнему будет работать.

Clemens 14.06.2024 21:44

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

Clemens 14.06.2024 21:47

@Clemens «Помимо этого, все еще неправильно, что элемент управления знает тип своего родителя». Я думал, что вся цель шаблона MVVM в противоположном. Представление должно знать о модели представления, но модель представления не должна знать о представлении. И следует избегать размещения кода в коде позади. Кроме того, не все элементы управления являются универсальными. Некоторые из них очень специализированы и предназначены только для работы в определенном контексте.

PatriceBG 14.06.2024 22:01

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

Clemens 14.06.2024 22:26

Во-вторых, MVVM не означает отсутствия кода. Это распространенное заблуждение, но оно совершенно неверное. MVVM — это разделение задач, что означает, что логика представления может быть реализована без знания конкретного представления, использующего модель представления. Это не имеет ничего общего с реализацией контроля. Посмотрите исходный код различных элементов управления в WPF. Ни один из них, даже самый сложный, не имеет частных моделей просмотра.

Clemens 14.06.2024 22:27

Даже неясно, об одном ли мы здесь говорим, поскольку мы не видели ни строчки вашего кода. Это обсуждение основано на предположении, что ваш элемент управления внутренне устанавливает для своего DataContext модель частного представления. Это правда? Если да, то вы на неправильном пути. Создание UserControl со знанием конкретной модели представления (или, точнее, DataContext с определенным набором свойств) — это другая история. Это был бы типичный подход MVVM.

Clemens 14.06.2024 22:45

Однако элемент управления по-прежнему не должен использовать частный экземпляр такой модели представления. Модель представления будет предоставляться путем наследования значения свойства DataContext, т. е. от родительского элемента элемента управления.

Clemens 14.06.2024 22:45

Нет, пользовательский элемент управления не устанавливает внутренний контекст данных. DataContext пользовательского элемента управления привязан к XAML в главном окне. У меня есть коллекция моделей представления в главном окне, а UserControl — это пользовательский интерфейс для взаимодействия с выбранным элементом в этой коллекции. Однако есть команды, которые необходимо выполнять в контексте главного окна, поскольку они потенциально влияют на другие элементы в коллекции, поэтому я привязал команду из главного окна к кнопке в пользовательском элементе управления. Я не вижу ничего плохого в этом дизайне.

PatriceBG 14.06.2024 23:18

Это превращается в религиозную дискуссию, а это не то, чего я хотел. Если нет возможности объявить тип DataContext предка в XAML, пусть будет так. Я буду жить с волнистыми подчеркиваниями.

PatriceBG 14.06.2024 23:19

@PatriceBG DataTemplates имеет свойство DataType. Я использую это; а также объявления «Тип DataContext DesignInstance». У меня есть «пользовательские элементы управления» с шестью синхронизированными ListViews, каждый из которых имеет разные «источники»; то есть другой «контекст данных» и «тип» для элемента DataTemplates представления списка. Мы не все религиозны.

Gerry Schmitz 14.06.2024 23:50

@Gerry Schmitz Да, я также широко использую тип DesignInstance. Чего я не знаю, как объявить тип DataContext предком. Я нашел, как объявить тип предка, но не тип его DataContext. Мой комментарий относительно религии заключался в том, было ли хорошим дизайном иметь пользовательский элемент управления с собственным DataContext, а не наследовать DataContext его родительского элемента, и, в моем конкретном случае, иметь кнопку в UserControl, привязанную к команде в DataContext родителя. Для меня это совершенно нормально. Если и есть недостаток, то я его не вижу.

PatriceBG 15.06.2024 00:27

@PatriceBG d:DataContext действителен только во время разработки. Знаете ли вы о DataContext во время выполнения?

emoacht 15.06.2024 01:33

@emoacht Да, я понимаю, что d:DataContext используется только во время разработки, я ищу эквивалент для указания типа DataContext родительского элемента. Во время выполнения все работает, пока в названии свойства нет опечатки.

PatriceBG 15.06.2024 01:55

@emoacht Я хотел бы получить предупреждение во время компиляции, если я ссылаюсь на несуществующее свойство, например тип. Ничего страшного, просто удобство. Как я уже писал, если это невозможно сделать, я буду с этим жить.

PatriceBG 15.06.2024 04:05

«Я хотел бы получить предупреждение во время компиляции, если я ссылаюсь на несуществующее свойство» --> «если есть недостаток, которого я не вижу». - Это главный момент: элементу управления невозможно узнать точный контекст дат. Если вы исправите это, введя жесткую связь с определенным типом, вы потеряете надежность, если только вы не начнете генерировать исключения, когда DataContext имеет неправильный тип. Вы теряете возможность использовать любой контекст данных в качестве источника данных для вашего элемента управления. Вы нарушаете множество распространенных и ценных принципов проектирования, таких как принцип открытия-закрытия.

BionicCode 15.06.2024 11:03

Вы не можете изменить тип контекста данных, не нарушив элемент управления. Это приводит ко всем известным проблемам, которых боится каждый разработчик. Проблемы, которые, скорее всего, рано или поздно обернутся против вас. И этого так легко избежать. Если вы предоставляете необходимые данные через свойства зависимостей, вы получаете все это: безопасность типов (это то, о чем вы думаете исключительно), правильное разделение внутренних элементов управления и контекста данных, что приводит к значительному улучшению ремонтопригодности и возможности повторного использования или удобства использования в целом.

BionicCode 15.06.2024 11:06

С точки зрения дизайна действительно нет смысла явно привязывать внутренние элементы к DataContext (если это предполагает ожидание определенного типа). Только представьте, насколько полезным был бы такой ListBox, который можно было бы использовать только с определенным DataContext. Надеюсь, мне удалось прояснить, почему ваш подход, заключающийся в том, чтобы сделать элемент управления зависимым от определенного типа данных, является дизайнерским запахом, которого так легко избежать.

BionicCode 15.06.2024 11:09

Далее мы можем сказать, что если неизбежно, что элемент управления должен полагаться на детали реализации DataContext, то вероятность того, что эта функциональность либо принадлежит представлению (что более вероятно), либо зависящая от представления функциональность принадлежит модели представления, чрезвычайно высока. В качестве примечания: MVVM — это шаблон архитектурного проектирования уровня приложения. Это связано с нагрузкой на компоненты уровня приложения, такие как бизнес-логика.

BionicCode 15.06.2024 11:10

Это не шаблон проектирования на уровне класса. Там не сказано, что каждый элемент управления является представлением и имеет модель представления. Элемент управления принадлежит представлению приложения и поэтому может ссылаться на класс функциональности модели представления приложения. MVVM также не сообщает, какой язык программирования вы используете (XAML или C#/код программной части). Подумайте об этом: если вы переместите код пользовательского интерфейса в класс модели представления, чтобы избежать кода программной части (поскольку вы считаете, что это нарушает MVVM), не нарушает ли это на самом деле MVVM? Перемещение кода пользовательского интерфейса из представления приложения в модель представления приложения никогда не может быть решением, совместимым с MVVM.

BionicCode 15.06.2024 11:12

Использование свойств зависимостей в качестве источника данных и DataContext только в качестве клиентского контекста для привязки данных. Эти свойства дадут вам проверку типа компилятора (это то, что вам нужно) и надежный дизайн класса, который ценит открытие-закрытие, сокрытие информации и другие принципы проектирования.

BionicCode 15.06.2024 11:15

@PatriceBG, с твоим дизайном все в порядке. Пожалуйста, не обращайте внимания на фанатиков, которые не могут ответить на вопрос WPF без лекции об их философии дизайна. К сожалению, нет, вы не можете добиться того, чего хотите. Редактор VS просто недостаточно сложен, чтобы распознать dctx относительного родительского источника.

Emperor Eto 15.06.2024 14:19

Возможно, я сказал слишком рано. Ответ Мустафы потенциально выглядит многообещающей альтернативой.

Emperor Eto 15.06.2024 14:39

@EmperorEto Спасибо, это прямой ответ, который я искал, если не тот, на который я надеялся. И да, ответ Мустафы решает мою главную проблему.

PatriceBG 15.06.2024 16:14

@PatriceBG немного не по теме, но вам может быть интересно - в MAUI вы можете указать тип контекста родительских данных относительного источника, не зная ничего о визуальном дереве. Он лазит по дереву за вас, пока не найдет что-то с dctx, соответствующим вашему типу. Это близко моему сердцу, потому что это был мой вклад в Xamarin Forms и предназначенный именно для этого сценария :) Не знаю, достаточно ли умно расширение редактора MAUI, чтобы распознать это и правильно выполнить intellisense на пути привязки, но это, безусловно, возможно. (а если бы не пиар, они бы развлеклись).

Emperor Eto 15.06.2024 17:36

@EmperorEto Спасибо, приятно это знать. Одна из тех частей информации, которая полезна при выборе платформы для нового приложения.

PatriceBG 15.06.2024 18:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
30
129
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я хотел бы получить предупреждение во время компиляции, если я ссылаюсь на несуществующее свойство. [См. комментарий]

#if DEBUG
    System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level =
    System.Diagnostics.SourceLevels.All;
#endif

Чтобы открыть XAML Binding Failures, выберите «Отладка» > «Windows».

Разве это не работает только во время выполнения?

Emperor Eto 15.06.2024 14:21

Работает на обоих, я этого не ожидал, Visual Studio много улучшений

Mustafa Mutasim 15.06.2024 14:24

Это отличная альтернатива. Это не устраняет волнистые синие подчеркивания, но приводит к сбоям привязки.

PatriceBG 15.06.2024 16:05

Рад, что это работает! в качестве обходного пути: I hope you keep in mind ценную информацию, предоставленную экспертами-программистами в этом долгом обсуждении, мы нигде не найдем, это требует многих лет упорного труда и знаний.

Mustafa Mutasim 15.06.2024 16:47

@Mustafa О, пожалуйста, Мустафа, у меня более 50 лет опыта в разработке программного обеспечения. Я изучил подводные камни и знаю, когда моя конструкция становится хрупкой. Я также узнал, когда применять принцип ЯГНИ. Мне не нужны были религиозные лекции о том, как использовать WPF. Ваш ответ был наиболее подходящим и именно тем, что мне нужно было узнать. Я благодарю вас за это.

PatriceBG 15.06.2024 17:39

Да, Мустафа, я согласен с @PatriceBG. Не уверен, что вы имеете в виду, но большая часть комментариев выше бесполезна. Никогда не путайте огромный # рядом с именем с мудростью или практическим опытом. Это просто означает, что у них здесь гораздо больше времени, чем у других. ВЫ предоставили очень полезный совет, который помог ФП и другим, кто задаст этот вопрос в будущем. ... скажем так, громко... люди, комментирующие выше, слишком часто больше заинтересованы в пропаганде своей конкретной философии дизайна (которая, по моему мнению, в высшей степени ошибочна), чем просто в ответах на заданные вопросы.

Emperor Eto 16.06.2024 03:37

А еще @PatriceBG 50 лет??? Черт, я думал, что я старый! 🤣

Emperor Eto 16.06.2024 03:38

@EmperorEto/PatriceBG, моё уважение вам, вашим словам и многолетнему опыту, GBU

Mustafa Mutasim 16.06.2024 09:33

@EmperorEto, да, в этом году я отмечаю 50-летие получения моего диплома инженера по компьютерным наукам в Университете Лилля (Франция) и 30-летие получения степени доктора философии в области компьютерных наук в Пенсильванском университете. И мне все еще нравится проектировать программное обеспечение, разрабатывать его и изучать новые технологии, надеюсь, еще на несколько лет. Держитесь, возраст не имеет большого значения, когда вы все еще активны и наслаждаетесь тем, что делаете.

PatriceBG 16.06.2024 17:56

@PatriceBG снимаю шляпу, Доктор! Мне приятно это слышать. Я тоже очень счастлив быть там, где я есть, но у меня все больше и больше случаются моменты «нынешние дети…», особенно на этом сайте. Желаю вам всего наилучшего, и если у вас есть еще вопросы по WPF, я буду начеку, надеюсь, не разжигая тотальную религиозную войну, лол.

Emperor Eto 16.06.2024 23:23

@EmperorEto Спасибо, я ценю это. Заботиться!

PatriceBG 17.06.2024 13:40

Другие вопросы по теме