我有一个启用多选的数据网格。我需要更改视图模型中的选择。但是,SelectedItems 属性是只读的,不能直接绑定到视图模型中的属性。那么我如何向视图表明选择已更改?
4 回答
安迪是对的。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;
}
}
请务必EnableRowVirtualisation="False"在 DataGrid 元素上进行设置,否则 IsSelected 绑定可能会失衡。
我没有使用DataGrid太多,但是一种适用于 的技术ListView是绑定到IsSelectedindividual 的属性ListViewItem。只需将其设置true为列表中的每个对象,然后它将被选中。
也许代表一行的对象DataGrid也有一个IsSelected属性,也可以这样使用?
伙计们,谢谢你的帮助。我的问题解决了。我认为这个问题对于新的 WPF 开发人员来说很常见,所以我将在这里重申我的问题以及更详细的解决方案,以防其他人遇到同样的问题。
问题:我有一个启用多选的音频文件数据网格。网格有多个列标题。用户可以多选几行。当他单击“播放”按钮时,音频文件将按列标题(例如 A 列)的顺序播放。播放开始时,多选被清除,仅突出显示当前播放的文件。当所有文件的播放结束时,将重新显示多选。回放在视图模型中完成。如您所见,这里有两个问题:1)如何从视图模型中选择当前正在播放的文件,以及 2)如何从视图模型中向视图发出播放完成并重新显示多选的信号。
解决方案:为了解决第一个问题,我在视图模型中创建了一个属性,该属性绑定到视图的 SelectedIndex 属性以选择当前正在播放的文件。为了解决第二个问题,我在视图模型中创建了一个布尔属性来指示播放完成。在后面的视图代码中,我订阅了布尔属性的 PropertyChanged 事件。在事件处理程序中,视图的 SelectedItems 属性是从保存的多选中重新创建的(SelectedItems 的内容被保存到列表中,并且 SelectedItems 在播放开始时被清除)。起初,我在重新创建 SelectedItems 时遇到了麻烦。事实证明,问题是由于重新创建是通过第二个线程启动的。WPF 不允许这样做。解决方案是使用 Dispatcher。Invoke() 让主线程完成工作。对于有经验的开发者来说,这可能是一个非常简单的问题,但对于新手来说,这是一个小挑战。无论如何,来自不同人的很多帮助。
只需在任何 MultiSelector 派生类上使用 SelectedItems ,并在它返回的 IList 上使用 Add、Remove、Clear 方法。