سؤال

لدي مربع نص مع contextmenu في ذلك. عندما ينقر المستخدم بزر الماوس الأيمن داخل مربع النص واختار Menuitem المناسب، أود الاستيلاء على CELARETTEXT في ViewModel. لم أجد طريقة جيدة للقيام بذلك بطريقة "MVVM".

حتى الآن لدي appliction الخاص بي باستخدام طريقة جوش سميث في MVVM. أنا أتطلع إلى Tranfer إلى Cinch. لست متأكدا مما إذا كان إطار Cinch يتعامل مع مشكلات مثل هذا. أفكار؟

هل كانت مفيدة؟

المحلول

لا توجد طريقة واضحة لربط SenearText بمصدر بيانات، لأنها ليست dependencyproperty ... ومع ذلك، من السهل جدا إنشاء خاصية مرفقة يمكنك ربطها بدلا من ذلك.

إليك التنفيذ الأساسي:

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:

<TextBox Text="{Binding Message}" u:TextBoxHelper.SelectedText="{Binding SelectedText}" />

نصائح أخرى

نموذج التطبيقات في إطار تطبيق WPF (WAF) اختار طريقة أخرى لحل هذه المشكلة. هناك مسموح ViewModel بالوصول إلى العرض من خلال واجهة (Iview)، وبالتالي يمكنه طلب SEARTEXT الحالي.

أعتقد أنه لا ينبغي أن تستخدم الربط في كل سيناريو. في بعض الأحيان تكتب عدد قليل من الأسطر الموجودة في الكود خلفها أكثر نظافة بكثير من استخدام فصول المساعد المتقدمة للغاية. لكن هذا مجرد رأيي :-)

جيش

أعلم أنه تم الرد عليه ومقبول، لكنني اعتقدت أنني سأضيف حلاي. يمكنني استخدام سلوك للجسر بين طراز العرض وصندوق النص. يحتوي السلوك على خاصية التبعية (caretpositionproperty) والتي يمكن ربط طريقتين لنموذج العرض. داخليا يتناول السلوك مع التحديثات من / إلى مربع النص.

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;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top