2010-04-05 51 views
1

我找到這個問題MVVM and the TextBox's SelectedText property。但是,我無法獲得解決方案。這是我的非工作代碼,我試圖在第二個文本框中顯示第一個文本框的選定文本。MVVM-我如何綁定到屬性,這不是DependancyProperty?

查看:

SelectedText和文本都是從我的ViewModel只是字符串屬性。

<TextBox Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}" Height="155" HorizontalAlignment="Left" Margin="68,31,0,0" Name="textBox1" VerticalAlignment="Top" Width="264" AcceptsReturn="True" AcceptsTab="True" local:TextBoxHelper.SelectedText="{Binding SelectedText, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}" /> 
     <TextBox Text="{Binding SelectedText, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Height="154" HorizontalAlignment="Left" Margin="82,287,0,0" Name="textBox2" VerticalAlignment="Top" Width="239" /> 

TextBoxHelper

public static class TextBoxHelper 
{ 
    #region "Selected Text" 
    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); 
     } 
    } 
    #endregion 

} 

我在做什麼錯?

回答

1

這不起作用的原因是屬性更改回調沒有引發(因爲您的虛擬機的綁定值與該屬性的元數據中指定的默認值相同)。但更基礎的是,當所選文本設置爲空時,您的行爲將會分離。在這種情況下,我傾向於使用另一個附加屬性來簡單地監視選定的文本,然後可以綁定SelectedText屬性。所以,像這樣:

#region IsSelectionMonitored 
public static readonly DependencyProperty IsSelectionMonitoredProperty = DependencyProperty.RegisterAttached(
    "IsSelectionMonitored", 
    typeof(bool), 
    typeof(PinnedInstrumentsViewModel), 
    new FrameworkPropertyMetadata(OnIsSelectionMonitoredChanged)); 

[AttachedPropertyBrowsableForType(typeof(TextBox))] 
public static bool GetIsSelectionMonitored(TextBox d) 
{ 
    return (bool)d.GetValue(IsSelectionMonitoredProperty); 
} 

public static void SetIsSelectionMonitored(TextBox d, bool value) 
{ 
    d.SetValue(IsSelectionMonitoredProperty, value); 
} 

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

     SetSelectedText(tb, tb.SelectedText); 
    } 
} 
#endregion 

#region "Selected Text" 
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) 
    { 
     tb.SelectedText = e.NewValue as string;    
    } 
} 

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

,然後在XAML,你必須將該屬性添加到您的第一個TextBox:

<TextBox ... local:TextBoxHelper.IsSelectionMonitored="True" local:TextBoxHelper.SelectedText="{Binding SelectedText, Mode=OneWayToSource}" /> 
-1

你需要一個普通的.NET屬性包裝了的DependencyProperty,有的像:

public string SelectedText 
{ 
    set {SetSelectedText(this, value);} 
... 

它不是由運行時所需(運行時使用的set/get),但它是由設計師和編譯器需要。

+0

的SelectedText屬性是一個附加的(依賴)房地產不是一個 '正常' 的依賴項屬性。有關概述,請參閱http://msdn.microsoft.com/en-us/library/ms749011.aspx – 2010-04-05 17:32:46

+0

好吧,我在閱讀原始問題時並不十分小心。但是你不認爲投票對於想要幫助的職位太過分了嗎? – Codism 2010-04-05 21:40:07

+0

不要讓自己陷入低谷。這只是一個工具,可以幫助人們從無用的人身上篩選有用的答案。如果您發現自己發佈了無用的答案,並且該答案已被降低,您可以將其刪除。 – RandomEngy 2010-04-06 20:56:06

1

爲了使SelectedTextChanged處理程序觸發SelectedText屬性,必須具有初始值。如果你不初始化這個值(string.Empty作爲最低限度),那麼這個處理程序永遠不會觸發,反過來你永遠不會註冊tb_SelectionChanged處理程序。

+0

我改變它是這樣的: 新的FrameworkPropertyMetadata(string.Empty,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,SelectedTextChanged)); 但它仍然無法正常工作。我誤解了你的意思嗎? – Justin 2010-04-05 18:26:16

+0

當我瀏覽示例代碼時,我將ViewModel上的SelectedText屬性的值設置爲string.Empty。更改PropertyMetadata不會導致更改的處理程序觸發。 – 2010-04-05 19:21:19

+0

我嘗試將SelectedText設置爲string.Empty,但在第一個文本框中選擇的文本仍未顯示在第二個文本框中。 – Justin 2010-04-06 00:07:43

0

你結合的嘗試你TextBoxText屬性綁定到TextBox當前數據上下文SelectedText財產。既然你有附加屬性的工作,不與物業掛您的數據上下文的,你需要在你的結合提供更多的信息:

<TextBox Text="{Binding local:TextBoxHelper.SelectedText, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" ... /> 

local已經與包含的CLR命名空間相關聯TextBoxHelper類。

+0

雖然在當前數據上下文中有SelectedText屬性,但它通過以下方式綁定到附加屬性: local:TextBoxHelper.SelectedText =「{Binding SelectedText,UpdateSourceTrigger = PropertyChanged,Mode = OneWayToSource}」 – Justin 2010-04-05 19:10:30

1

這個使用類TextBoxHelper爲我工作。正如其他提到的,您需要用非空值初始化TextBoxHelper的SelectedText屬性。不應將數據綁定到視圖上的字符串屬性(SelText),而應將其綁定到應實現INotifyPropertyChanged的虛擬機的字符串屬性。

XAML:

<Window x:Class="TextSelectDemo.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:TextSelectDemo" 
    Height="300" Width="300"> 
    <StackPanel> 
     <TextBox local:TextBoxHelper.SelectedText="{Binding Path=SelText, Mode=TwoWay}" /> 
     <TextBox Text="{Binding Path=SelText}" /> 
    </StackPanel> 
</Window> 

後面的代碼:

using System.ComponentModel; 
using System.Windows; 

namespace TextSelectDemo 
{ 
    public partial class Window1 : Window, INotifyPropertyChanged 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      SelText = string.Empty; 

      DataContext = this; 
     } 

     private string _selText; 
     public string SelText 
     { 
      get { return _selText; } 
      set 
      { 
       _selText = value; 
       if (PropertyChanged != null) 
       { 
        PropertyChanged(this, new PropertyChangedEventArgs("SelText")); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 
} 
相關問題