Как выглядит простая реализация ParentAdapter? - PullRequest
0 голосов
/ 02 февраля 2009

Я пытаюсь написать реализацию ParentAdapter; Я заинтересован в обеспечении поддержки времени разработки для некоторых элементов управления WPF, которые я пишу, и именно так вы управляете пользовательской логикой для переопределения элементов в различных элементах управления контейнера. Я начал с малого с идеи создания класса StackPanel, который позволял бы создавать элементы Button во время разработки (да, я знаю, что самой панели также необходим код для поддержки этого). Я начал с того, что, как я полагал, было бы самым простым из возможных ParentAdapter:

using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Windows.Design.Interaction;
using Microsoft.Windows.Design.Model;

namespace ControlLibrary.Design
{
    internal class SimplePanelParentAdapter : ParentAdapter
    {
        public override bool CanParent(ModelItem parent, Type childType)
        {
            return (childType == typeof(Button));
        }

        // moves the child item into the target panel; in this case a SimplePanel
        public override void Parent(ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope undoContext = newParent.BeginEdit())
            {
                // is this correct?
                //child.Content.SetValue("I'm in a custom panel!");
                SimplePanel pnl = newParent.GetCurrentValue() as SimplePanel;
                pnl.Children.Add(child.GetCurrentValue() as UIElement);                
                undoContext.Complete();
            }

        }

        public override void RemoveParent(ModelItem currentParent, ModelItem newParent, ModelItem child)
        {
            // No special things need to be done, right?
            child.Content.SetValue("I was in a custom panel.");
        }
    }
}

Когда я работаю с этим во время разработки, как только я перетаскиваю кнопку на свою пользовательскую панель, из глубины кода VS выбрасывается NullReferenceException. Мой код не выдает исключение, потому что я могу пройти весь путь через мой метод; стек вызовов указывает, что код в Microsoft.Windows.Design.Developer.dll вызывает исключение.

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

1 Ответ

0 голосов
/ 03 февраля 2009

Я нашел ответ на свой вопрос сам. Проблема вызвана редактированием модели вместо оболочки ModelItem. То, что я должен был сделать (и работает), выглядит примерно так:

using System;
using System.Windows.Controls;
using Microsoft.Windows.Design.Interaction;
using Microsoft.Windows.Design.Model;

namespace ControlLibrary.Design
{
    internal class SimplePanelParentAdapter : ParentAdapter
    {
        public override bool CanParent(ModelItem parent, Type childType)
        {
            return (childType == typeof(Button));
        }

        // moves the child item into the target panel; in this case a SimplePanel
        public override void Parent(ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope undoContext = newParent.BeginEdit())
            {
                ModelProperty prop = newParent.Properties["Children"];
                ModelItemCollection items = (ModelItemCollection)prop.Value;
                items.Add(child);

                undoContext.Complete();
            }

        }

        public override void RemoveParent(ModelItem currentParent, ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope scope = child.BeginEdit())
            {
                ModelProperty prop = currentParent.Properties["Children"];
                ((ModelItemCollection)prop.Value).Remove(child);

                scope.Complete();
            }
        }
    }
}

Я был сбит с толку, когда писал первый код, и не знал, как я должен был вызывать Add () для свойства Children; похоже, ModelProperty.Value оборачивает коллекции с ModelItemCollection, поэтому, если вы не сделаете все возможное, чтобы ваш класс использовал тупой интерфейс, это должно работать.

...