2010-02-11 17 views
12

मेरे पास एक संदर्भ बॉक्स के साथ टेक्स्टबॉक्स है। जब उपयोगकर्ता टेक्स्टबॉक्स के अंदर सही क्लिक करता है और उचित मेनू इटैम चुनता है, तो मैं अपने व्यूमोडेल में चयनित टेक्स्ट को पकड़ना चाहता हूं। मुझे यह "एमवीवीएम" तरीका करने का अच्छा तरीका नहीं मिला है।एमवीवीएम और टेक्स्टबॉक्स की चयनित टेक्स्ट संपत्ति

अब तक मेरे पास जोश स्मिथ के एमवीवीएम के तरीके का उपयोग करने की मेरी प्रशंसा है। मैं सिंच पर ट्रांफर करने के लिए देख रहा हूँ। सुनिश्चित नहीं है कि सिंच ढांचा इस तरह के मुद्दों को संभालेगा। विचार?

उत्तर

18

डेटा स्रोत पर चयनित टेक्स्ट को बाध्य करने का कोई सीधा तरीका नहीं है, क्योंकि यह निर्भरता प्रॉपर्टी नहीं है ... हालांकि, एक संलग्न संपत्ति बनाने में काफी आसान है जिसे आप बाध्य कर सकते हैं।

यहाँ एक बुनियादी कार्यान्वयन है:

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}" /> 
+0

धन्यवाद !! यह चाल है। इतना स्पष्ट और मैंने इसे याद किया। एक बार फिर धन्यवाद। – Eric

+0

मैं CaretIndex संपत्ति के लिए ऐसा करने की कोशिश कर रहा हूं लेकिन ऐसा लगता है कि यह काम नहीं कर रहा है। क्या आप – TheITGuy

+0

@TheITGuy की सहायता कर सकते हैं, न कि आपके कोड को देखे बिना ... आपको शायद एक नया प्रश्न बनाना चाहिए (आप यहां लिंक पोस्ट कर सकते हैं, अगर मैं कर सकता हूं तो मैं जवाब दूंगा) –

2

WPF Application Framework (WAF) में नमूना अनुप्रयोगों इस समस्या को हल करने के लिए एक और रास्ता चुना है। ViewModel को इंटरफ़ेस (IView) के माध्यम से दृश्य तक पहुंचने की अनुमति है और इसलिए यह वर्तमान चयनित टेक्स्ट का अनुरोध कर सकता है।

मेरा मानना ​​है कि बाध्यकारी प्रत्येक परिदृश्य में उपयोग नहीं किया जाना चाहिए। कभी-कभी कोड में कुछ पंक्तियां लिखना अत्यधिक उन्नत सहायक कक्षाओं का उपयोग करने से कहीं अधिक स्वच्छ है। लेकिन यह सिर्फ मेरी राय :-)

jbe

+0

इस समाधान का उपयोग सार्वजनिक पाठक के साथ किसी भी स्ट्रिंग प्रॉपर्टी पर चयनित टेक्स्ट के मान को धक्का देने में सक्षम होने का लाभ है। लचीलापन तर्कसंगत रूप से कोड की अतिरिक्त रेखाओं से अधिक है। इसके अलावा, कुछ छोटे बदलावों के साथ, समाधान को चयनस्टार्ट और चयन चयन गुणों को बांधने के लिए उपयोग किया जा सकता है, जिससे दृश्य मॉडल आसानी से सेट हो सकते हैं, और टेक्स्ट चयन प्राप्त हो सकते हैं। – Gusdor

1

मैं जानता हूँ कि यह जवाब दिया गया है और स्वीकार किए जाते हैं, लेकिन मैं मैं अपने समाधान जोड़ना होगा सोचा। मैं व्यू मॉडल और टेक्स्टबॉक्स के बीच पुल करने के लिए एक व्यवहार का उपयोग करता हूं। व्यवहार में एक निर्भरता संपत्ति है (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; 
    } 
}