2010-08-30 76 views
2

在Silverlight MVVMLight 4.0應用程序中,我有一個列表框,一個文本框和一個複選框。 列表框的ItemsSource綁定到viewmodel中的對象列表。 列表框的SelectedItem對視圖模型中的對象(SelectedActivity)進行雙向綁定。Silverlight MVVM - Twoway綁定未在Listbox上觸發點擊

文本框的Text和複選框的IsSelected屬性都是雙向綁定到ViewModel中的SelectedActivity對象(Name和Selected properties)。 沒有隱藏代碼。

這工作正常:更改文本框中的名稱或選中/取消選中複選框,然後選項卡將更改該對象的基礎屬性。

但是,當我更改名稱(或選中狀態),然後立即單擊列表中的另一個項目時,更改未註冊。

有沒有人有這方面的解決方法?

親切的問候,

卡雷爾

這是XAML:

<ListBox Height="251" HorizontalAlignment="Left" Margin="11,39,0,0" Name="activitiesListBox" ItemsSource="{Binding Activities.Items}" VerticalAlignment="Top" Width="139" 
      SelectedItem="{Binding Activities.SelectedActivity, Mode=TwoWay}"> 

這是活動類保持綁定到列表中的項目:

public class CLJActivitiesViewModel : ViewModelBase 
{ 
    /// <summary> 
    /// Initializes a new instance of the ActivitiesViewModel class. 
    /// </summary> 
    public CLJActivitiesViewModel() 
    { 
     ////if (IsInDesignMode) 
     ////{ 
     //// // Code runs in Blend --> create design time data. 
     ////} 
     ////else 
     ////{ 
     //// // Code runs "for real": Connect to service, etc... 
     ////} 
    } 


    #region items 
    /// <summary> 
    /// The <see cref="Items" /> property's name. 
    /// </summary> 
    public const string ItemsPropertyName = "Items"; 

    private ObservableCollection<CLJActivityViewModel> m_Items = null; 

    /// <summary> 
    /// Gets the Items property. 
    /// TODO Update documentation: 
    /// Changes to that property's value raise the PropertyChanged event. 
    /// This property's value is broadcasted by the Messenger's default instance when it changes. 
    /// </summary> 
    public ObservableCollection<CLJActivityViewModel> Items 
    { 
     get 
     { 
      return m_Items; 
     } 

     set 
     { 
      if (m_Items == value) 
      { 
       return; 
      } 

      var oldValue = m_Items; 
      m_Items = value; 

      RaisePropertyChanged(ItemsPropertyName, oldValue, value, true); 
     } 
    } 
    #endregion 

    #region SelectedActivity 
    /// <summary> 
    /// The <see cref="SelectedActivity" /> property's name. 
    /// </summary> 
    public const string SelectedActivityPropertyName = "SelectedActivity"; 

    private CLJActivityViewModel m_SelectedActivity = null; 

    /// <summary> 
    /// Gets the SelectedActivity property. 
    /// TODO Update documentation: 
    /// Changes to that property's value raise the PropertyChanged event. 
    /// This property's value is broadcasted by the Messenger's default instance when it changes. 
    /// </summary> 
    public CLJActivityViewModel SelectedActivity 
    { 
     get 
     { 
      return m_SelectedActivity; 
     } 

     set 
     { 
      if (m_SelectedActivity == value) 
      { 
       return; 
      } 

      var oldValue = m_SelectedActivity; 
      m_SelectedActivity = value; 

      RaisePropertyChanged(SelectedActivityPropertyName, oldValue, value, true); 
     } 
    } 
    #endregion 



    public override void Cleanup() 
    { 
     // Clean own resources if needed 

     base.Cleanup(); 
    } 
}   
+0

這將有助於如果您發佈至少是你的viewmodel/view代碼的相關部分。您的列表是ObservableCollection,而您的視圖模型是否實現INotifyPropertyChanged? – 2010-08-30 16:44:37

+0

是的,列表綁定到一個ObservableCollection並且視圖模型正在實現INotifyPropertyChanged。我使用了MVVMLight模板。 我會用相關的代碼更新這個問題。 – Karel 2010-08-31 08:13:07

回答

1

我遇到了同樣的問題。我必須在用戶輸入文本時觸發更新,以便我可以進行一些驗證。

實現這一目的的一種簡單方法是創建一個自定義行爲,然後您可以將其添加到任何TextBox

煤礦如下:

public static class TextChangedBindingBehavior 
{ 
    public static readonly DependencyProperty InstanceProperty = 
     DependencyProperty.RegisterAttached("Instance", typeof(object), typeof(TextChangedBindingBehavior), new PropertyMetadata(OnSetInstanceCallback)); 


    public static object GetInstance(DependencyObject obj) 
    { 
     return (object)obj.GetValue(InstanceProperty); 
    } 

    public static void SetInstance(DependencyObject obj, object value) 
    { 
     obj.SetValue(InstanceProperty, value); 
    } 

    private static void OnSetInstanceCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var textBox = d as TextBox; 
     if (textBox != null) 
     { 
      textBox.TextChanged -= OnTextChanged; 
      textBox.TextChanged += OnTextChanged; 
     } 
    } 

    private static void OnTextChanged(object sender, TextChangedEventArgs e) 
    { 
     var textBox = (TextBox)sender; 

     if(!DesignerProperties.GetIsInDesignMode(textBox)) 
     { 
      textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); 
     } 
    } 
} 

,你將其設置爲TextBox像(Behaviors是我把類上面的命名空間):

<TextBox Behaviors:TextChangedBindingBehavior.Instance="" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" /> 
+0

謝謝,我會試試看。 – Karel 2010-09-01 15:42:05

+0

太棒了,完美的作品! – Karel 2010-09-01 15:47:26

1

我已經用TextBox碰到類似的問題,但沒有看到它影響複選框。 TextBox問題發生,因爲綁定文本得到更新,然後焦點丟失。這就是爲什麼如果你先選中,然後改變你的選擇,它會像你期望的那樣工作。如果您直接更改選擇,則由於焦點丟失消息到達太遲,所以文本不會更新。

處理此問題的一種方法是每次用戶鍵入文本框中的文本時強制綁定更新。你可以自定義行爲來保持mvvm。

相關問題