Почему избыточные XAML / код за объявлениями базового класса для пользовательского элемента управления вызывают наблюдаемые проблемы? - PullRequest
0 голосов
/ 28 апреля 2020

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

У меня есть пользовательский элемент управления, который функционирует как боковая панель навигации, которая позволяет пользователю выбирать из списка опций слева и отображает результат в панели сетки справа. Для правого контента я разработал абстрактный базовый класс под названием BaseSectionView, который наследуется от ContentControl и содержит несколько сигналов (таких как занятые спиннеры, обработчики событий всплывающего окна и т. Д. c.), Которые я хочу использовать во всем приложении.

Я наследую от BaseSectionView, чтобы создать определенный c раздел, который может отображаться в элементе ContentControl на правой панели моего ListNavigationControl.

Здесь находятся два проекта: проект для моих пользовательских элементов управления в одном пространстве имен, для которого определен шаблон c .xaml, и проект, реализующий все эти вещи конкретно.

Объявление BaseSectionView:

namespace my.custom.control.namespace 
{
    public abstract class BaseSectionView : ContentControl, INotifyPropertyChanged, IDisposable {
        ...
    }
}

BaseSectionView не имеет xaml, но получает информацию о стиле и шаблоне из generi c .xaml в моем проекте пользовательского элемента управления.

Следующий элемент управления наследуется от BaseSectionView. Когда я впервые попробовал это, я объявил BaseSectionView в качестве базового класса в ОБА XAML и коде позади, и это вызвало странную проблему. Теперь я делаю это только в xaml.

<Controls:BaseSectionView x:Class="my.implemented.control.nameSpace.MySectionView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:local="clr-namespace:my.implemented.control.namespace"
    xmlns:Controls="clr-namespace:my.custom.control.namespace"
    mc:Ignorable="d">

    ... some uninteresting markup ...

</Controls:BaseSectionView>

Код объявления:

    public partial class MySectionView
    {
        public MySectionView(...) : base(...)
        {
            ...
            InitializeComponent();
        }
        ...
    }

Наконец, код ListNavigationControl (я выделил строку, которая важна для этого вопроса). Я просто показываю фрагмент кода, который обрабатывает пользователь, щелкающий по различным элементам навигации в виде списка слева, и устанавливает представление <ContentControl Name="SelectedSectionViewer" Grid.Column="2" /> в xaml.

namespace my.custom.control.namespace 
{
    public partial class ListNavigationControl : UserControl
    {
        ... constructors and such ...

        private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_updatingSelectedSectionInternal && e.AddedItems.Count > 0)
            {
                BaseSectionView newSection = e.AddedItems[0] as BaseSectionView;

                if (newSection != null)
                {
                    _updatingSelectedSectionInternal = true;

                    // Set new page as active
                    _selectedSection.Model.IsActive = false;
                    _selectedSection = newSection;
                    SelectedSectionViewer.Content = _selectedSection; // <-------- This line is significant. 
                    _selectedSection.Model.IsActive = true;
                    _updatingSelectedSectionInternal = false;
                }
            }
        }

        ...
    }
}

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

Когда я с избыточностью объявлял базовый класс MySectionView в и xaml, и код позади (что, как я понимаю, является ошибкой), я все еще мог заставить это работать (albietly badly: информация о файле generi c .xaml не будет применяться к базовому контролю и другим симптомам). Однако чтобы заставить его работать, мне пришлось изменить отмеченную строку выше на:

SelectedSectionViewer.Content = _selectedSection.Conent

В противном случае ничто не будет отображаться в элементе SelectedSectionViewer.

Здесь есть два вопроса:

A) Почему объявление базового класса моего конкретного представления как в xaml, так и в коде позади не позволило SelectedSectionViewer выше отобразить представление ( и запретить применение информации стиля в generi c .xaml в классе пользовательских элементов управления к пользовательскому элементу управления)?

B) В чем именно разница между получением содержимого из представления с использованием свойства .Content и если потребляющий элемент отображает сам контент?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...