WPF - MVVM:SelectionChanged后的ComboBox值 [英] WPF - MVVM: ComboBox value after SelectionChanged

查看:2189
本文介绍了WPF - MVVM:SelectionChanged后的ComboBox值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新的C#和MVVM,我花了一整天试图获得 ComboBox 的价值到我的ViewModel在 SelectionChanged 。我已经设法使用 CallMethodAction InvokeCommandAction 与资源:




  • System.Windows.Interactivity.dll

  • Microsoft.Expression.Interactions.dll



我的问题是这两个方法都返回 ComboBox



我花了几个小时搜索SO和Google的解决方案,所以我想知道如果别人也是。



我的代码如下:



MainWindow.xaml

 < Window x:Class =SelectionChange.MainWindow
xmlns =http: 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 =MainWindowWidth =300Height =300>
< Window.DataContext>
< vm:ViewModel />
< /Window.DataContext>
< Grid>
< ComboBox Name =SelectBoxVerticalAlignment =TopSelectedIndex =0>
< i:Interaction.Triggers>
< i:EventTrigger EventName =SelectionChanged>
< si:CallMethodAction MethodName =SelectionChangedTargetObject ={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

 命名空间SelectionChange 
{
using System;
使用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

 命名空间SelectionChange 
{
using System;
使用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);
}
}
}





修改:我的解决方案



原来我不明白绑定足够好,而是试图以一种相当复杂的方式实现一个简单的东西!而不是使用依赖,我现在已经实现了我需要使用常规绑定。例如,我已经将 TextBox 绑定到 ComboBox 的 SelectedIndex code>,使用 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 =MainWindowWidth =300Height =300>
< Window.DataContext>
< vm:ViewModel />
< /Window.DataContext>
< Grid>
< Grid.ColumnDefinitions>
< ColumnDefinition Width =Auto/>
< ColumnDefinition Width =*/>
< /Grid.ColumnDefinitions>

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

<! - TextBox显示ComboBox的SelectedIndex - >
< TextBox Text ={Binding selectedIndex}Grid.Column =1VerticalAlignment =Top/>
< / Grid>
< / Window>

ViewModel.cs

 命名空间SelectionChange 
{
using System;
using System.ComponentModel;
using System.Windows.Controls;

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

//存储/检索ComboBox的SelectedIndex
private int _SelectedIndex;
public int SelectedIndex {get;组; }

//绑定到ComboBox的SelectedItem的属性
private ComboBoxItem _SelectedItem;
public ComboBoxItem SelectedItem
{
get {return _SelectedItem; }
set
{
_SelectedItem = value;

// SelectedItem的内容
string Content =(string)value.Content;

// SelectedItem的父级(即ComboBox)
ComboBox SelectBox =(ComboBox)value.Parent;

// ComboBox的SelectedIndex
int Index = SelectBox.SelectedIndex;

//在属性
中存储SelectedIndex SelectedIndex = Index;

//使用存储属性的名称提高PropertyChanged
RaisePropertyChanged(SelectedIndex);
}
}

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


解决方案>

为什么不用更简单的方法

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

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

 列表< string& _source = new List< string> {Item 1,Item 2,Item 3}; 
public List< string>源
{
get {return _source; }
}

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

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

同时不要忘记实现INotifyPropertyChanged接口_source


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:

  • 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 after the change?

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

My code is below:

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




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.

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

解决方案

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

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

这篇关于WPF - MVVM:SelectionChanged后的ComboBox值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆