gpt4 book ai didi

c# - 使用 MVVM Light 解开两个控件上的 EventToCommand

转载 作者:行者123 更新时间:2023-11-30 17:51:26 25 4
gpt4 key购买 nike

大家好,我是 WPF 的新手,我已经开始使用基于 mvvm light 框架的 mvvm 模式实现一个应用程序。我发现它很棒但是我在应该一起交互的控件上使用两个 EventToCommand 时遇到了问题。我猜我做错了什么……你能帮我查清楚到底是什么吗?

我有一个带有两个控件的窗口:一个允许选择名称 的组合框和一个显示标题 的文本框。名称具有默认标题(在 ViewModel 的构造函数中对示例进行了硬编码,请参见下文)。因此,当用户选择名称时,文本框应显示默认标题。但是,标题是可编辑的,这意味着用户可以更改标题(只要他不再次更改名称)。

在下面的示例中,我使用 MVVM 模式和 MVVM Light 框架实现了这一点。Ok 按钮仅绑定(bind)到在 OutPut 窗口中记录值的命令(以查看 ViewModel 中的属性值)。

正如您将在源代码注释中看到的那样,问题出在 NameSelectionChanged 命令触发带有“过时值”的 CaptionTextChanged 命令这一事实。现在,我通过设置一个 bool 值来实现一个 hacky 解决方法(不在下面的代码中),该值在执行 NameSelectionChanged 中的 RaisePropertyChanged 时忽略 CaptionTextChanged 中的代码,但它并不令人满意。

XAML 中的 View

<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# 中的 View 模型

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

Ps: targeted .NET是3.5,MVVMLight的版本是4.1.27.1

最佳答案

您不需要使用任何事件在 WPF 中执行此操作。如果按照惯例在 View 模型上实现 INotifyPropertyChanged 接口(interface),只需使用属性 Bindings 就可以实现所有这些...这个怎么样:

private ObservableCollection<string> columnNames = new 
ObservableCollection<string>();
public ObservableCollection<string> ColumnNames
{
get { return columnNames; }
set { columnNames = value; NotifyPropertyChanged("ColumnNames"); }
}

private string selectedColumnName;
public string SelectedColumnName
{
get { return selectedColumnName; }
set
{
selectedColumnName = value;
NotifyPropertyChanged("SelectedColumnName");
int index = _names.IndexOf(value); // <<< Changes are reflected here
Caption = _captions[index];
}
}

private string caption = string.Empty;
public string Caption
{
get { return caption; }
set { caption = value; NotifyPropertyChanged("Caption"); }
}

在 XAML 中:

<Grid>
<ComboBox ItemsSource="{Binding ColumnNames}" SelectedItem="{Binding
SelectedColumnName}" x:Name="NamesComboBox" HorizontalAlignment="Left"
VerticalAlignment="Top" Width="120" />
<TextBox Text="{Binding Caption, Mode=TwoWay}" Name="CaptionTextBox"
HorizontalAlignment="Left" Height="23" Margin="0,45,0,0" TextWrapping="Wrap"
VerticalAlignment="Top" Width="120" />
<Button Content="Ok" Command="{Binding ClickOk}" HorizontalAlignment="Left"
Margin="120,170,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>

告诉我进展如何。

关于c# - 使用 MVVM Light 解开两个控件上的 EventToCommand,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19489238/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com