WPF,带有MVVM(Caliburn.Micro)的可绑定(bind)richTextBox-文档已经属于另一个RichTextBox

标签 wpf mvvm richtextbox flowdocument caliburn.micro

我有一个非常有趣的问题。我在 WPF 应用程序中使用了这些技术:Caliburn.Micro 和 MEF。

我从 View 模型打开新窗口(不是屏幕)。它运作良好。

初始化 View 模型 我有这个方法,它打开新的 WPF 窗口,而不是 shell 中的屏幕。

...

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

展示窗口类看起来像这样:
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));
    }
}

我使用事件聚合器将消息从初始化 View 模型发送到新窗口。

在我添加richtebox控件之前,一切都运行良好。我需要可绑定(bind)的富文本框。所以我

使用 Jason Mueller 的可绑定(bind)版本 (http://social.msdn.microsoft.com/forums/en-US/wpf/thread/f77c011a-0aba-449f-b6f4-920e58ebf997/)

新 View 模型 看起来像这样:
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 类中,我在 View 中的 RichTextBox 上绑定(bind)了 Conversation 属性。

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

问题是。
  • 我从 Init-View-Model 调用方法 public IEnumerable Send() -> 它调用了 New-View-Model 的 cotructor -> 并打开了新窗口。没错
  • 比我第二次调用方法 public IEnumerable Send() 我得到这个错误: System.Argument.Exception {“文档已经属于另一个 RichTextBox。”}

  • 我在可绑定(bind)的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)
    

    问题出在哪里,我尝试了很多方法,但任何一个都不起作用。感谢您的建议和帮助。我很无奈。

    最佳答案

    我的解决方案:

    我用 标记我的新 View 模型[PartCreationPolicy(CreationPolicy.NonShared)] ,因为 MEF 导出的默认生命周期是共享的(单例)。

    关于WPF,带有MVVM(Caliburn.Micro)的可绑定(bind)richTextBox-文档已经属于另一个RichTextBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4511097/

    相关文章:

    wpf - dataGrid 上的 SharedSizeGroup

    c# - WPF C# LINQ : Operator '&&' cannot be applied to operands of type 'string' and 'string' query

    c# - 在 WPF 中加载 BitmapImage 的源代码?

    asp.net - ASP.NET 2.0 的最佳免费富文本框?

    reactjs - 当 onChange 被调用时,react-quill 失去焦点

    c# 重写 RichTextBox 粘贴函数 - Win Form App

    .net - 在Wpf应用中查看Byte [] Pdf

    c# - 如何双向绑定(bind) ViewModel 和复选框?

    wpf - 如何在 WPF 应用程序中限定 NHibernate session 和事务

    android - 不赞成使用ViewModelProviders.of()时,如何在 Activity 和服务之间共享相同的ViewModel?