首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVVM和TextBox的SelectedText属性

MVVM和TextBox的SelectedText属性
EN

Stack Overflow用户
提问于 2010-02-12 00:33:12
回答 5查看 11.8K关注 0票数 16

我有一个里面有ContextMenu的TextBox。当用户在TextBox中右击并选择适当的MenuItem时,我想在视图模型中抓取SelectedText。我还没有找到用"MVVM“的方式来做这件事的好方法。

到目前为止,我的应用程序使用了Josh Smith的MVVM方法。我想转到辛奇去。不确定Cinch框架是否能处理这样的问题。有什么想法?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-02-12 01:14:41

没有直接的方法可以将SelectedText绑定到数据源,因为它不是DependencyProperty...但是,创建一个可以绑定的附加属性是非常容易的。

这是一个基本的实现:

代码语言:javascript
复制
public static class TextBoxHelper
{

    public static string GetSelectedText(DependencyObject obj)
    {
        return (string)obj.GetValue(SelectedTextProperty);
    }

    public static void SetSelectedText(DependencyObject obj, string value)
    {
        obj.SetValue(SelectedTextProperty, value);
    }

    // Using a DependencyProperty as the backing store for SelectedText.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectedTextProperty =
        DependencyProperty.RegisterAttached(
            "SelectedText",
            typeof(string),
            typeof(TextBoxHelper),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, SelectedTextChanged));

    private static void SelectedTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        TextBox tb = obj as TextBox;
        if (tb != null)
        {
            if (e.OldValue == null && e.NewValue != null)
            {
                tb.SelectionChanged += tb_SelectionChanged;
            }
            else if (e.OldValue != null && e.NewValue == null)
            {
                tb.SelectionChanged -= tb_SelectionChanged;
            }

            string newValue = e.NewValue as string;

            if (newValue != null && newValue != tb.SelectedText)
            {
                tb.SelectedText = newValue as string;
            }
        }
    }

    static void tb_SelectionChanged(object sender, RoutedEventArgs e)
    {
        TextBox tb = sender as TextBox;
        if (tb != null)
        {
            SetSelectedText(tb, tb.SelectedText);
        }
    }

}

然后您可以在XAML中像这样使用它:

代码语言:javascript
复制
<TextBox Text="{Binding Message}" u:TextBoxHelper.SelectedText="{Binding SelectedText}" />
票数 23
EN

Stack Overflow用户

发布于 2010-02-15 00:44:46

中的示例应用程序选择了另一种方法来解决此问题。在那里,允许ViewModel通过接口(IView)访问视图,因此它可以请求当前的SelectedText。

我认为不应该在每个场景中都使用绑定。有时,在后台代码中编写几行代码比使用非常高级的助手类要干净得多。但这只是我的观点:-)

jbe

票数 1
EN

Stack Overflow用户

发布于 2011-08-23 16:58:10

我知道它已经被回答和接受了,但我想我会添加我的解决方案。我使用行为在视图模型和TextBox之间架起桥梁。行为有一个依赖属性(CaretPositionProperty),它可以双向绑定到视图模型。在内部,该行为处理与TextBox之间的更新。

代码语言:javascript
复制
public class SetCaretIndexBehavior : Behavior<TextBox>
    {
        public static readonly DependencyProperty CaretPositionProperty;
        private bool _internalChange;

    static SetCaretIndexBehavior()
    {

    CaretPositionProperty = DependencyProperty.Register("CaretPosition", typeof(int), typeof(SetCaretIndexBehavior), new PropertyMetadata(0, OnCaretPositionChanged));
}

public int CaretPosition
{
    get { return Convert.ToInt32(GetValue(CaretPositionProperty)); }
    set { SetValue(CaretPositionProperty, value); }
}

protected override void OnAttached()
{
    base.OnAttached();
    AssociatedObject.KeyUp += OnKeyUp;
}

private static void OnCaretPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var behavior = (SetCaretIndexBehavior)d;
    if (!behavior._internalChange)
    {
        behavior.AssociatedObject.CaretIndex = Convert.ToInt32(e.NewValue);
    }
}

    private void OnKeyUp(object sender, KeyEventArgs e)
    {
        _internalChange = true;
        CaretPosition = AssociatedObject.CaretIndex;
        _internalChange = false;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2245928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档