C# WPF列表框选择已更改的MVVM
我的WPF应用程序中有一个列表框。我知道如何使用selectionchanged事件。然而,我试图遵循MVVM设计。然而,我不知道如何做到这一点 我已经做了一个按钮,但不确定我是否可以做同样的事情C# WPF列表框选择已更改的MVVM,c#,wpf,mvvm,C#,Wpf,Mvvm,我的WPF应用程序中有一个列表框。我知道如何使用selectionchanged事件。然而,我试图遵循MVVM设计。然而,我不知道如何做到这一点 我已经做了一个按钮,但不确定我是否可以做同样的事情 <Button Grid.Column="0" Name="buttImport" Content="Import File" Command="{Binding CommandButtImport}" Style="{StaticResource ButtonTe
<Button Grid.Column="0" Name="buttImport"
Content="Import File"
Command="{Binding CommandButtImport}"
Style="{StaticResource ButtonTemplate}"/>
编辑请忽略上面的代码
<DataGrid Grid.Row="1" Grid.Column="0"
ItemsSource="{Binding SelectedItem.DuplicateSecurities, ElementName=dataGridOrders}"
SelectedItem="{Binding SelectedItem.Security, ElementName=dataGridOrders}">
我已经更改了我的代码,因此在我当前拥有的代码下面重新发布。我有一个奇怪的问题。XAML-Main代码包含我的datagrid的代码。App-XAML下面的块包含了我大部分应用程序的样式,但只是一个snipet
也
代码行添加在XAML-Main代码中我的datagrid下面,用于测试目的
<ListBox ItemsSource="{Binding SelectedItem.DuplicateSecurities, ElementName=dataGridOrders}"
SelectedItem="{Binding SelectedItem.Security, ElementName=dataGridOrders}"/>
包含其他类的OrderBlocks类
public class OrderBlocks : INotifyPropertyChanged
{
private List<Order> _orders;
[XmlElement("tF_Transactions")]
public List<Order> Orders { get { return _orders; } set { _orders = value; OnPropertyChanged("Orders"); } }
}
编辑-我的代码现在可以工作了请查看下面适合我的代码片段
<DataGrid Grid.Row="1" Grid.Column="0"
ItemsSource="{Binding SelectedItem.DuplicateSecurities, ElementName=dataGridOrders}"
SelectedItem="{Binding SelectedItem.Security, ElementName=dataGridOrders}">
在ViewModel中将ListBox
SelectionChanged
事件绑定到命令的示例
<ListBox x:Name="myListBox" ItemsSource="{Binding SomeCollection}">
<ie:Interaction.Triggers>
<ie:EventTrigger EventName="SelectionChanged">
<ie:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}" CommandParameter="{Binding ElementName=myListBox, Path=SelectedItem}"/>
</ie:EventTrigger>
</ie:Interaction.Triggers>
</ListBox >
这个特定的示例使用Prism MVVM框架,但是您也可以将相同的思想应用到您正在使用的任何其他MVVM框架中
希望这对使用MVVM的
SelectionChanged
非常简单有帮助:
一种方法是绑定到列表框
的SelectedIndex
属性,并在VM的属性设置器中相应地执行操作,就像在属性更改时触发一样
例如:
在本例中,只要选定索引发生更改,该项的值就会增加一
主要是:
public int SelectedIndex {
get {
return _selectedIndex;
}
set {
if (_selectedIndex == value) {
return;
}
// At this point _selectedIndex is the old selected item's index
_selectedIndex = value;
// At this point _selectedIndex is the new selected item's index
RaisePropertyChanged(() => SelectedIndex);
}
}
xaml只是:
<ListBox ItemsSource="{Binding Items}" SelectedIndex="{Binding SelectedIndex}" />
Items
是我们绑定到的项的集合。问题是……你能发布你尝试过的内容和这些尝试的结果吗?我上面发布的示例适用于按钮,但我想知道当选择更改时如何对列表框执行此操作。对于MVVM,将ListBox
的SelectedItem
或SelectedIndex
属性绑定到VM,并在属性的setter中执行您需要执行的操作,因为当ListBox
中的选择相应更改时,它会触发。这就是你的问题所在吗?我没有任何结果,因为我不确定该怎么办。我刚刚在互联网上搜索,没有任何乐趣绑定SelectedIndex
对我来说似乎是个坏主意。。。如何获得所选内容所代表的实际项目?此外,这将意味着您必须实现所有依赖于setter中新选定项的代码(而不是对子方法的划分)。另一件事是,这将允许直接从ViewModel
更改选择,而不仅仅是UI,如果应用程序没有这样的用途,这是您不想要的-case@OmribitanItems[SelectedIndex]
我的观点是,您不希望在视图模型的整个生命周期内保留该选择项的实例,而您只在实际选择发生更改时才需要它。@Omribitan抱歉,在此您不能同意。如果您不想在setter中执行此操作,请将其分派回同一线程或安装INPC watcher并在那里执行相应的操作这将允许直接从ViewModel而不仅仅是UI更改选择,这是您不想要的,
err what?是虚拟机更改了从虚拟机中选择的索引
,这是完全有效的设计。在某些情况下,您可能希望将索引设置为-1以删除选择和数百个其他用例。@Omribitan VM通常与视图具有11关系。只要让虚拟机做它想做的“管理相应的视图”。这是WPF。你可以想出10种方法来解决这个问题。我唯一不同意的是“将SelectedIndex绑定到VM是错误的”。选择您喜欢的任何方法:如果任何人在使用此答案中提供的解决方案时出现错误,请参考下面我的答案:您希望顶部的以下命名空间使用“ie:”xmlns:ie=“clr namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity”
谢谢,这有助于我上路。我只想提一下。您需要将System.Windows.Interactive添加到项目的引用中。对于那些使用常见的RelayCommand的用户,只需像常规命令一样将其连接起来,就可以在参数中获得所选对象。谢谢,这是一个非常好的解决方案。。。我补充说,如果您使用“caliburn.micro”,您应该使用“RelayCommand”而不是“DelegateCommand”,它将在fin中工作。这种解决方案是胡说八道。处理事件不会违反MVVM。MVVm并不意味着对所有事情都使用ICommand
(强制)。这是一篇老文章,但我希望你现在更了解它。您可以始终绑定到SelectedItem
rSelectedIndex
以触发视图模型中的操作。
public class Security : INotifyPropertyChanged
{
private string _id;
public string ID
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("ID");
}
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public Security() { }
public Security(string newID, string newName)
{
ID = newID;
Name = newName;
}
<DataGrid Grid.Row="1" Grid.Column="0"
ItemsSource="{Binding SelectedItem.DuplicateSecurities, ElementName=dataGridOrders}"
SelectedItem="{Binding SelectedItem.Security, ElementName=dataGridOrders}">
<ListBox x:Name="myListBox" ItemsSource="{Binding SomeCollection}">
<ie:Interaction.Triggers>
<ie:EventTrigger EventName="SelectionChanged">
<ie:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}" CommandParameter="{Binding ElementName=myListBox, Path=SelectedItem}"/>
</ie:EventTrigger>
</ie:Interaction.Triggers>
</ListBox >
public class myViewModel
{
public myViewModel()
{
SelectedItemChangedCommand = new DelegateCommand<object>((selectedItem) =>
{
// Logic goes here
});
}
public List<SomeData> SomeCollection { get; set; }
public DelegateCommand<object> SelectedItemChangedCommand { get; set; }
}
public int SelectedIndex {
get {
return _selectedIndex;
}
set {
if (_selectedIndex == value) {
return;
}
// At this point _selectedIndex is the old selected item's index
_selectedIndex = value;
// At this point _selectedIndex is the new selected item's index
RaisePropertyChanged(() => SelectedIndex);
}
}
<ListBox ItemsSource="{Binding Items}" SelectedIndex="{Binding SelectedIndex}" />