2013-10-27 68 views
9

我是C#和MVVM的新手,我花了一整天的時間嘗試將我的ViewModel的ComboBox的值設置爲SelectionChanged。我已成功使用或者CallMethodActionInvokeCommandAction與資源弄明白:WPF - MVVM:SelectionChanged後的ComboBox值

  • System.Windows.Interactivity.dll
  • Microsoft.Expression.Interactions.dll

我的問題是,這兩種方法返回ComboBox前值已改變。任何人都可以解釋如何獲得值後的變化?

我花了數小時搜索SO和Google尋求解決方案,所以我想知道其他人是否也是如此。任何建議將被認真考慮!

我的代碼如下:

MainWindow.xaml

<Window x:Class="SelectionChange.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
     xmlns:si="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" 
     xmlns:vm="clr-namespace:SelectionChange" 
     Title="MainWindow" Width="300" Height="300"> 
    <Window.DataContext> 
     <vm:ViewModel /> 
    </Window.DataContext> 
    <Grid> 
     <ComboBox Name="SelectBox" VerticalAlignment="Top" SelectedIndex="0"> 
      <i:Interaction.Triggers> 
       <i:EventTrigger EventName="SelectionChanged"> 
        <si:CallMethodAction MethodName="SelectionChanged" TargetObject="{Binding}" /> 
        <!--<i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding ElementName=SelectBox, Path=Text}" />--> 
       </i:EventTrigger> 
      </i:Interaction.Triggers> 
      <ComboBoxItem Content="Item 1" /> 
      <ComboBoxItem Content="Item 2" /> 
      <ComboBoxItem Content="Item 3" /> 
     </ComboBox> 
    </Grid> 
</Window> 

ViewModel.cs

namespace SelectionChange 
{ 
    using System; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Input; 

    public class ViewModel 
    { 
     public ViewModel() 
     { 
      SelectionChangedCommand = new SelectionChangedCommand(); 
     } 

     public ICommand SelectionChangedCommand 
     { 
      get; 
      set; 
     } 

     public void SelectionChanged(object sender, EventArgs e) 
     { 
      ComboBox SelectBox = (ComboBox)sender; 
      MessageBox.Show("Called SelectionChanged: " + SelectBox.Text); 
     } 
    } 
} 

SelectionChangedCommand.cs

namespace SelectionChange 
{ 
    using System; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Input; 

    public class SelectionChangedCommand : ICommand 
    { 
     public SelectionChangedCommand() 
     { 
     } 

     public event EventHandler CanExecuteChanged; 

     public bool CanExecute(object parameter) 
     { 
      return true; 
     } 

     public void Execute(object parameter) 
     { 
      MessageBox.Show("Executed SelectionChangedCommand: " + parameter); 
     } 
    } 
} 




編輯:我的解決方案

原來我不明白Binding不夠好,而是試圖實現東西在一個相當複雜的方式簡單!現在我已經使用常規綁定實現了我所需的功能,而不是使用依賴關係。作爲示例,我已將TextBox綁定到ComboBoxSelectedIndex,其使用INotifyPropertyChanged進行更新。

MainWindow.xaml Screenshot

MainWindow.xaml

<Window x:Class="SelectionChange.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:vm="clr-namespace:SelectionChange" 
     Title="MainWindow" Width="300" Height="300"> 
    <Window.DataContext> 
     <vm:ViewModel /> 
    </Window.DataContext> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 

     <ComboBox SelectedItem="{Binding SelectedItem}" SelectedIndex="0" Grid.Column="0" VerticalAlignment="Top"> 
      <ComboBoxItem Content="Item 1" /> 
      <ComboBoxItem Content="Item 2" /> 
      <ComboBoxItem Content="Item 3" /> 
     </ComboBox> 

     <!-- TextBox to display the ComboBox's SelectedIndex --> 
     <TextBox Text="{Binding SelectedIndex}" Grid.Column="1" VerticalAlignment="Top" /> 
    </Grid> 
</Window> 

ViewModel.cs

namespace SelectionChange 
{ 
    using System; 
    using System.ComponentModel; 
    using System.Windows.Controls; 

    public class ViewModel : INotifyPropertyChanged 
    { 
     public ViewModel() 
     { 
     } 

     // Property to store/retrieve ComboBox's SelectedIndex 
     private int _SelectedIndex; 
     public int SelectedIndex { get; set; } 

     // Property to bind to ComboBox's SelectedItem 
     private ComboBoxItem _SelectedItem; 
     public ComboBoxItem SelectedItem 
     { 
      get { return _SelectedItem; } 
      set 
      { 
       _SelectedItem = value; 

       // SelectedItem's Content 
       string Content = (string)value.Content; 

       // SelectedItem's parent (i.e. the ComboBox) 
       ComboBox SelectBox = (ComboBox)value.Parent; 

       // ComboBox's SelectedIndex 
       int Index = SelectBox.SelectedIndex; 

       // Store the SelectedIndex in the property 
       SelectedIndex = Index; 

       // Raise PropertyChanged with the name of the stored property 
       RaisePropertyChanged("SelectedIndex"); 
      } 
     } 

     // INotifyPropertyChanged 
     public event PropertyChangedEventHandler PropertyChanged; 
     private void RaisePropertyChanged(string PropertyName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); 
     } 
    } 
} 
+0

如果我明白你想要做什麼,我認爲這將有助於http://stackoverflow.com/questions/4765362/mvvm-combobox -binding – kenny

+0

我只想給你一個想法。那麼如何將SelectedItems屬性綁定到ViewModel中的綁定模式TwoWay?無需收聽SelectionChanged事件或創建命令。每當SelectedItems值發生變化時,您將在ViewModel中的屬性設置器中收到通知。試試看。 –

+0

。嘗試這樣的事情。 – srsyogesh

回答

19

爲什麼不這樣做的簡單的方法

<ComboBox MaxHeight="25" 
      ItemsSource="{Binding Source}" 
      SelectedItem="{Binding TheSelectedItem, Mode=TwoWay}" /> 

在您的視圖模型聲明組合框項目和使用屬性「來源」,使其恢復到視圖

List<string> _source = new List<string>{"Item 1", "Item 2", "Item 3"}; 
public List<string> Source 
{ 
    get { return _source; } 
} 

然後定義一個包含所選項目的房產

string _theSelectedItem = null; 
public string TheSelectedItem 
{ 
    get { return _theSelectedItem; } 
    set { _theSelectedItem = value; } // NotifyPropertyChanged 
} 

另外不要忘記實現INotifyPropertyChanged接口,同時設置_source

+0

這是最接近我結束了,我想,取決於你想用ComboBox做什麼,可能是解決方案(對於其他人)。 @ aks81,謝謝你的回答! –

+0

不客氣@AlistairTweed。 – Sandesh

1

如果你只是想獲得通知當你當前項目的變化,爲什麼不使用工具這些已經是WPF的一部分,而不是所有這些依賴關係。

首先獲取您的集合的底層視圖,並使用它的CurrentChanged事件。

ComboBoxList = new ObservableCollection<string>(); 
var view = CollectionViewSource.GetDefaultView(ComboBoxList); 
view.MoveCurrentTo(ComboBoxList[0]); 
view.CurrentChanged += new EventHandler(ComboBoxCurrentChanged); 

在XAML中你只綁定您的收藏和設置IsSynchronizedWithCurrentItem爲true。

<ComboBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding ComboBoxList}"/>