Call RichTextBox.ScrollToEnd() from View Model cla

2019-08-14 01:28发布

问题:

Hi I try solve this, in WPF I use Caliburn Micro framework. In View I have bindable richtextbox control, I bind from view model class property type of FlowDocument.

I need have a way how can I call method ScrollToEnd on richetextbox control in view.

Is it possible? Because in view model class I don’t have instance of richtextbox.

Thank for idead.

回答1:

A similar question is asked here with a solution. http://social.msdn.microsoft.com/Forums/en/wpf/thread/67b618aa-f62e-43f8-966c-48057f4d4e0c



回答2:

Sometimes it makes sense to call UI code from the code behind file (if other solutions complicate things). Remember: patterns are just recommendations not the script. One could even argue that exposing a FlowDocument from view model makes the view model too aware about UI. But you did it because it was easier, right?

If you don't want to make this call from code behind, here are two options:

  • Consider injecting an interface to the view model, with one ScrollToEnd() method. View implements this method and view model calls it whenever it feels necessity.
  • Expose an event from view model ScrollToEndRequested. View subscribes to this event and acts accordingly whenever it's fired.

Other options (like attached behaviors) might be more suitable, but they are really depend on your context.



回答3:

I provided an answer to a question about setting the focus to a specific control using Caliburns IResult here. You should be able to use the same concept to get hold of the RichTextBox in order to invoke ScrollToEnd. I will not duplicate the entire explanation here, go to that question for the ideas, but the following IResult implementation (as a guide) should put you on the right track.

public class RichTextBoxScrollToEnd : ResultBase
{
    public RichTextBoxScrollToEnd()
    {

    }

    public override void Execute(ActionExecutionContext context)
    {
        var view = context.View as UserControl;

        List<Control> richTextBoxes =
            view.GetChildrenByType<Control>(c => c is RichTextBox);

        var richTextBox = richTextBoxes.FirstOrDefault();

        if (richTextBox != null)
            richTextBox.Dispatcher.BeginInvoke(() =>
        {
            richTextBox.ScrollToEnd();
        });

        RaiseCompletedEvent();
    }
}

If you have multiple RichTextBoxes in your view you could provide a parameter to the constructor of RichTextBoxScrollToEnd which is the name of the specific control you want to target and then filter richTextBoxes using that name i.e.

var richTextBox = richTextBoxes.FirstOrDefault(c => c.Name == _nameOfControl);

See the referenced question for more details though.