C# WPF - MVVM:SelectionChanged 后的组合框值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19620581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 15:26:34  来源:igfitidea点击:

WPF - MVVM: ComboBox value after SelectionChanged

c#wpfmvvmbindingcombobox

提问by Alistair Tweed

I am new to C# and MVVM, and I've spent all day trying to get the value of a ComboBoxto my ViewModel on SelectionChanged. I have managed to figure it out using either CallMethodActionor InvokeCommandActionwith the resources:

我是 C# 和 MVVM 的新手,我花了一整天的时间试图ComboBoxSelectionChanged. 我已经设法通过使用CallMethodActionInvokeCommandAction使用资源来解决这个问题:

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

My problem is that both these methods return the value of the ComboBoxbefore it has changed. Could anyone explain how to get the value afterthe change?

我的问题是这两种方法都返回ComboBox更改之前的值。任何人都可以解释如何在更改获取值?

I have spent hours searching through SO and Google for a solution, so I wonder if others are too. Any advice will be appreciated!

我花了几个小时通过 SO 和 Google 搜索解决方案,所以我想知道其他人是否也是如此。任何建议将被认真考虑!

My code is below:

我的代码如下:

MainWindow.xaml

主窗口.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

视图模型.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

选择更改命令.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);
        }
    }
}




Edit: My Solution




编辑:我的解决方案

It turns out I didn't understand Bindingwell enough and instead was trying to implement something simple in a rather complicated way! Instead of using dependencies, I have now achieved what I needed using regular bindings. As an example, I've bound a TextBoxto the SelectedIndexof the ComboBox, which gets updated using INotifyPropertyChanged.

事实证明我理解Binding得不够好,而是试图以相当复杂的方式实现一些简单的东西!我现在使用常规绑定实现了我需要的功能,而不是使用依赖项。例如,我将 a 绑定TextBoxSelectedIndexComboBox,它使用 进行更新INotifyPropertyChanged

MainWindow.xaml Screenshot

MainWindow.xaml 截图

MainWindow.xaml

主窗口.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

视图模型.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));
        }
    }
}

采纳答案by Sandesh

Why not do it the simpler way

为什么不以更简单的方式做呢

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

In your ViewModel declare the combo box items and use a property "Source" to return it to the view

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

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

Then define one property which holds the selected item

然后定义一个属性来保存所选项目

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

Also don't forget to implement the INotifyPropertyChanged interface while setting the _source

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

回答by dowhilefor

If you just want to get notified when your current item changes, why not use tools that are already part of WPF instead of all these dependencies.

如果您只想在当前项目更改时收到通知,为什么不使用已经是 WPF 一部分的工具而不是所有这些依赖项。

First get the underlying view to your collection and use the CurrentChanged event on it.

首先获取您的集合的基础视图并在其上使用 CurrentChanged 事件。

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

In your xaml you just bind your collection and set IsSynchronizedWithCurrentItemto true.

在您的 xaml 中,您只需绑定您的集合并设置IsSynchronizedWithCurrentItem为 true。

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