我有一个启用了多选功能的数据网格。我需要在视图模型中更改选择。然而,SelectedItems属性是只读的,无法直接绑定到视图模型中的属性。那么,我该如何向视图发出选择已更改的信号?
我有一个启用了多选功能的数据网格。我需要在视图模型中更改选择。然而,SelectedItems属性是只读的,无法直接绑定到视图模型中的属性。那么,我该如何向视图发出选择已更改的信号?
Andy是正确的。 DataGridRow.IsSelected 是一个依赖属性,可以通过数据绑定来控制从ViewModel中选择。以下示例代码演示了这一点:
<Window x:Class="DataGridMultiSelectSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tk="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
Title="Window1" Height="300" Width="300">
<StackPanel>
<tk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" EnableRowVirtualization="False">
<tk:DataGrid.Columns>
<tk:DataGridTextColumn Header="Value" Binding="{Binding Value}" />
</tk:DataGrid.Columns>
<tk:DataGrid.RowStyle>
<Style TargetType="tk:DataGridRow">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</tk:DataGrid.RowStyle>
</tk:DataGrid>
<Button Content="Select Even" Click="Even_Click" />
<Button Content="Select Odd" Click="Odd_Click" />
</StackPanel>
</Window>
using System.ComponentModel;
using System.Windows;
namespace DataGridMultiSelectSample
{
public partial class Window1
{
public Window1()
{
InitializeComponent();
DataContext = new[]
{
new MyViewModel {Value = "Able"},
new MyViewModel {Value = "Baker"},
new MyViewModel {Value = "Charlie"},
new MyViewModel {Value = "Dog"},
new MyViewModel {Value = "Fox"},
};
}
private void Even_Click(object sender, RoutedEventArgs e)
{
var array = (MyViewModel[]) DataContext;
for (int i = 0; i < array.Length; ++i)
array[i].IsSelected = i%2 == 0;
}
private void Odd_Click(object sender, RoutedEventArgs e)
{
var array = (MyViewModel[])DataContext;
for (int i = 0; i < array.Length; ++i)
array[i].IsSelected = i % 2 == 1;
}
}
public class MyViewModel : INotifyPropertyChanged
{
public string Value { get; set; }
private bool mIsSelected;
public bool IsSelected
{
get { return mIsSelected; }
set
{
if (mIsSelected == value) return;
mIsSelected = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
确保在DataGrid元素上设置EnableRowVirtualisation="False"
,否则会存在选择绑定失效的风险。
EnableRowVirtualisation="False"
,因为如果没有它,会出现绑定不在新行上的错误。 - Colonel PanicDataGrid
的使用不是很熟悉,但是一个适用于ListView
的技巧是绑定到单个ListViewItem
的IsSelected
属性。只需将每个对象的该属性设置为true
,那么它就会被选中。DataGrid
行的对象也有一个IsSelected
属性,可以这样使用吗?各位,感谢您的帮助。我的问题已经解决了。我认为这个问题对于新的WPF开发人员来说是非常普遍的,因此我会在这里重新阐述我的问题以及解决方案的更多细节,以防其他人遇到类似的问题。
问题:我有一个启用了多选的音频文件数据网格。该网格有多个列标题。用户可以多选几行。当他点击播放按钮时,音频文件将按照一个列标题(比如列A)的顺序播放。当播放开始时,多选将被清除,并且只会突出显示当前正在播放的文件。当所有文件的播放完成后,多选将重新显示。播放是在视图模型中完成的。正如您所看到的,这里有两个问题:1)如何从视图模型中选择当前正在播放的文件,2)如何向视图发送信号,表示播放已完成并重新显示多选。
解决方案:为了解决第一个问题,我在视图模型中创建了一个属性,该属性绑定到视图的SelectedIndex属性以选择当前正在播放的文件。为了解决第二个问题,我在视图模型中创建了一个布尔属性,指示播放已完成。在视图的代码后台中,我订阅了布尔属性的PropertyChanged事件。在事件处理程序中,从保存的多选(在播放开始时,将SelectedItems的内容保存到列表中,并清除SelectedItems)重新创建了视图的SelectedItems属性。起初,我在重新创建SelectedItems时遇到了麻烦。原来问题是由于重新创建是通过第二个线程启动的。WPF不允许这样做。解决此问题的方法是使用Dispatcher.Invoke()让主线程完成工作。对于经验丰富的开发人员来说,这可能是一个非常简单的问题,但对于新手来说,它是一个小挑战。无论如何,感谢不同人士的帮助。