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
WPF - MVVM: ComboBox value after SelectionChanged
提问by Alistair Tweed
I am new to C# and MVVM, and I've spent all day trying to get the value of a ComboBox
to my ViewModel on SelectionChanged
. I have managed to figure it out using either CallMethodAction
or InvokeCommandAction
with the resources:
我是 C# 和 MVVM 的新手,我花了一整天的时间试图ComboBox
在SelectionChanged
. 我已经设法通过使用CallMethodAction
或InvokeCommandAction
使用资源来解决这个问题:
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 ComboBox
before 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 Binding
well 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 TextBox
to the SelectedIndex
of the ComboBox
, which gets updated using INotifyPropertyChanged
.
事实证明我理解Binding
得不够好,而是试图以相当复杂的方式实现一些简单的东西!我现在使用常规绑定实现了我需要的功能,而不是使用依赖项。例如,我将 a 绑定TextBox
到SelectedIndex
的ComboBox
,它使用 进行更新INotifyPropertyChanged
。
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 IsSynchronizedWithCurrentItem
to true.
在您的 xaml 中,您只需绑定您的集合并设置IsSynchronizedWithCurrentItem
为 true。
<ComboBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding ComboBoxList}"/>