您好,我对WPF不太熟悉,最近开始使用基于mvvm模式的应用程序,并使用了mvvm light框架。我觉得这个框架很棒,但是在两个控件上使用两个EventToCommand时遇到了问题。我猜测我做错了什么...您能帮我找出问题所在吗?
我有一个窗口,里面有两个控件:一个下拉框可以选择“名称”,一个文本框显示“标题”。每个名称都有一个默认标题(在ViewModel的构造函数中硬编码为示例)。因此,当用户选择一个名称时,文本框应该显示默认标题。但是,标题是可编辑的,这意味着用户可以更改标题(只要他不再次更改名称)。
在下面的示例中,我使用MVVM模式和MVVM Light框架来实现这一点。确定按钮仅绑定到一个命令,该命令记录OutPut窗口中的值(以查看ViewModel中的属性值)。
正如您在源代码注释中所看到的,问题在于NameSelectionChanged命令使用“过时的值”触发CaptionTextChanged命令。目前,我通过设置一个布尔值来实现了一个hacky的解决方法(不在下面的代码中),该值在NameSelectionChanged中执行RaisePropertyChanged时忽略CaptionTextChanged中的代码,但这并不是很令人满意。
XAML中的视图
<Window x:Class="TwoControls.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:TwoControls"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<vm:DummyViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Window.Resources>
<Window.DataContext>
<Binding Path="GetViewModel" Source="{StaticResource Locator}" />
</Window.DataContext>
<Grid>
<ComboBox ItemsSource="{Binding ColumnNames}" x:Name="NamesComboBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding NameSelectionChanged}" CommandParameter="{Binding SelectedValue, ElementName=NamesComboBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
<TextBox Text="{Binding Caption, Mode=TwoWay}" Name="CaptionTextBox" HorizontalAlignment="Left" Height="23" Margin="0,45,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<cmd:EventToCommand Command="{Binding CaptionTextChanged}" CommandParameter="{Binding Text, ElementName=CaptionTextBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<Button Content="Ok" Command="{Binding ClickOk}" HorizontalAlignment="Left" Margin="120,170,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
C#中的视图模型
public class MainViewModel : ViewModelBase
{
private readonly List<string> _names;
private readonly string[] _captions;
public MainViewModel()
{
_names = new List<string>(new[]{"TOTO","TATA","TUTU"});
_captions = new[] {"toto", "tata", "tutu"};
}
public string Name { get; set; }
public string Caption { get; set; }
public ICommand NameSelectionChanged
{
get
{
return new RelayCommand<string>((input) =>
{
Name = input;
int index = _names.IndexOf(input);
Caption = _captions[index];
//Trigger the execution of CaptionTextChanged with the old value of the TextBox
//even if Caption and TextBox.Text are bound TwoWay....
base.RaisePropertyChanged(()=>this.Caption);
});
}
}
public ICommand CaptionTextChanged
{
get
{
return new RelayCommand<string>((input) =>
{
Caption = input;
});
}
}
public ICommand ClickOk
{
get
{
return new RelayCommand(() =>
{
Console.WriteLine("Name=" + Name +";" +"Caption=" + Caption);
});
}
}
public List<string> ColumnNames
{
get { return _names; }
}
}
附注:目标 .NET 版本为 3.5,MVVMLight 的版本为 4.1.27.1