Хобрук: Ваш путь к мастерству в программировании

WPF, RichTextBox с возможностью привязки с MVVM (Caliburn.Micro) — документ уже принадлежит другому RichTextBox

У меня есть очень интересная проблема. Я использую эти технологии в приложении WPF: Caliburn.Micro и MEF.

Я открываю новое окно (не экран) из модели просмотра. Это работает хорошо.

В Init-View-Model у меня есть этот метод, который открывает новое окно WPF, а не экран в оболочке.

...

        public IEnumerable<IResult> Send()
        {
            yield return new ShowWindow("NewScreen")
                .InitializeWith(_service.DetailData(Account,_selectedFriend.Key));
        }
...

Класс ShowWindow выглядит следующим образом:

public class ShowWindow : IResult
{
    readonly Type _windowType;
    readonly string _name;

    [Import]
    public IShellViewModel Shell { get; set; }

    Action<object> _initializationAction = window => { };

    public ShowWindow InitializeWith<T>(T argument)
    {
        _initializationAction = window =>
        {
            var initializable = window as IInitializable<T>;
            if (initializable != null)
                initializable.Initialize(argument);
        };
        return this;
    }

    public ShowWindow(string name)
    {
        _name = name;
    }

    public ShowWindow(Type windowType)
    {
        _windowType = windowType;
    }

    public void Execute(ActionExecutionContext context)
    {
        var window = !string.IsNullOrEmpty(_name)
            ? IoC.Get<object>(_name)
            : IoC.GetInstance(_windowType, null);

        _initializationAction(window);

        IoC.Get<IWindowManager>().Show(window);

        Completed(this, new ResultCompletionEventArgs());
    }

    public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };

    public static ShowWindow Of<T>()
    {
        return new ShowWindow(typeof(T));
    }
}

Я использую агрегатор событий при отправке сообщений из модели представления инициализации в новое окно.

Все работало хорошо, пока я не добавил управление Richtebox. Мне нужен привязываемый RichTextBox. Так что я

используйте привязываемую версию Джейсона Мюллера (http://social.msdn.microsoft.com/forums/en-US/wpf/thread/f77c011a-0aba-449f-b6f4-920e58ebf997/)

New-View-Model выглядит следующим образом:

public class NewViewModel : Screen, IInitializable<DetailData>, IHandle<string>
{
    private IEventAggregator _eventAgg;

    private FlowDocument _conversation;

    //bind on document of richtextBox
    public FlowDocument Conversation
    {
        get { return _conversation; }
        set
        {
            _conversation = value;
            NotifyOfPropertyChange("Conversation");
        }
    }

    [ImportingConstructor]
    public NewViewModel(IEventAggregator eventAgg)
    {
        _eventAgg = eventAgg;
        _eventAgg.Subscribe(this);

        **//I think problem is here
        _conversation = new FlowDocument();**
    }

    public void Handle(string message)
    {
        Conversation.Blocks
            .Add(new Paragraph(new Run(message)));
    }
}

В классе New-View-Model я привязываю свойство Conversation к RichTextBox в View.

Просмотр:

   <Controls:BindableRichTextBox    Document="{Binding Path=Conversation, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                                    VerticalScrollBarVisibility="Auto" 
                                    HorizontalScrollBarVisibility="Auto"
                                    FontSize="13"
                                    Margin="4,4,4,4" 
                                    Grid.Row="0" />

Проблема в том.

  1. Я вызываю метод public IEnumerable Send() из Init-View-Model -> он вызывает cotructor New-View-Model -> и открывает новое окно. Это верно

  2. Затем я вызываю метод public IEnumerable Send() второй раз и получаю эту ошибку: System.Argument.Exception {"Документ уже принадлежит другому RichTextBox."}

Эту ошибку я получаю в классе привязываемого RichTextBox.

...

        protected override void OnInitialized(EventArgs e)
        {
            // Hook up to get notified when DocumentProperty changes.
            DependencyPropertyDescriptor descriptor = DependencyPropertyDescriptor.FromProperty(DocumentProperty, typeof(BindableRichTextBox));
            descriptor.AddValueChanged(this, delegate
            {
                // If the underlying value of the dependency property changes,
                // update the underlying document, also.
**line 54:        base.Document = (FlowDocument)GetValue(DocumentProperty);**

            });

            // By default, we support updates to the source when focus is lost (or, if the LostFocus
            // trigger is specified explicity.  We don't support the PropertyChanged trigger right now.
            this.LostFocus += new RoutedEventHandler(BindableRichTextBox_LostFocus);

            base.OnInitialized(e);

        }

....

Я думаю, проблема в том, что он вызывает только один раз конструктор New-View-Model. Поэтому я пять раз вызываю метод Send, но он вызывает конструктор New-View-Model только один раз. Как это решить?

Трассировки стека:

   at System.Windows.Controls.RichTextBox.set_Document(FlowDocument value)
   at Spirit.Controls.BindableRichTextBox.b__0(Object , EventArgs ) in C:\Users\Jan\Documents\Visual Studio 2010\Projects\C#\Pokec_Messenger\ver.beta\Pokec__Messenger\Spirit_v1.2\Controls\BindableRichTextBox.cs:line 54
   at MS.Internal.ComponentModel.PropertyChangeTracker.OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
   at System.Windows.DependentList.InvalidateDependents(DependencyObject source, DependencyPropertyChangedEventArgs sourceArgs)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp)
   at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.Activate(Object item)
   at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
   at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
   at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
   at MS.Internal.Data.DataBindEngine.Run(Object arg)
   at MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e)
   at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.Resize(ICompositionTarget resizedCompositionTarget)
   at System.Windows.Interop.HwndTarget.OnResize()
   at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

В чем проблема, я пробовал много способов, но ни один не работает. Спасибо за ваш совет и помощь. Я беспомощен.


Ответы:


1

МОЕ РЕШЕНИЕ:

Я помечаю свою новую модель представления [PartCreationPolicy(CreationPolicy.NonShared)], поскольку по умолчанию время жизни экспортов MEF — Shared (singleton).

26.12.2010
Новые материалы

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

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

Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

стройный-i18следующий
Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..

Обзор 20 основных и современных методов работы с массивами в JavaScript
Вы знаете их всех? В этом коротком посте я покажу сводку методов, доступных в JavaScript для работы с массивами. Я надеюсь, что вы найдете это полезным! В конце поста вы найдете ссылку на..

Да, но я чувствую необходимость указать, что это или не единственные два.
Да, но я чувствую необходимость указать, что это или не единственные два. Обучение с подкреплением (в качестве примера) также является важным.