WPF - MVVM:SelectionChanged 后的 ComboBox 值

Posted

技术标签:

【中文标题】WPF - MVVM:SelectionChanged 后的 ComboBox 值【英文标题】:WPF - MVVM: ComboBox value after SelectionChanged 【发布时间】:2013-11-06 09:16:11 【问题描述】:

我是 C# 和 MVVM 的新手,我整天都在尝试将 ComboBox 的值传递给 SelectionChanged 上的 ViewModel。我已经设法使用CallMethodActionInvokeCommandAction 和资源来解决这个问题:

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

<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));
        
    

【问题讨论】:

如果我理解你想要做什么,我认为这将有助于***.com/questions/4765362/mvvm-combobox-binding 我只是给你一个想法。如何使用绑定模式 TwoWay 将 SelectedItems 属性绑定到 ViewModel 中的属性?无需监听 SelectionChanged 事件或创建命令。每当 SelectedItems 值发生更改时,您都会在 ViewModel 中属性的设置器内收到通知。试试看。 。试试这样的。 感谢所有 3 条建议!他们帮助我找到了解决方案。 【参考方案1】:

为什么不做更简单的方法

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

在您的 ViewModel 中声明组合框项目并使用属性“Source”将其返回给视图

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

另外不要忘记在设置_source时实现INotifyPropertyChanged接口

【讨论】:

这与我最终得到的结果最接近,我想,这取决于你想用 ComboBox 做什么,可能是解决方案(对于其他人)。 @aks81,谢谢你的回答!【参考方案2】:

如果您只想在当前项目更改时收到通知,为什么不使用已经是 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"/>

【讨论】:

以上是关于WPF - MVVM:SelectionChanged 后的 ComboBox 值的主要内容,如果未能解决你的问题,请参考以下文章

有没有wpf mvvm框架的详细讲解?

WPF MVVM

wpf mvvm获取列表行数据

MVVM设计模式和在WPF中的实现 事件绑定

WPF开发微信三高仿微信对话框

wpf mvvm模式 Icommand接口应该如何理解?