我有一个使用 Caliburn.Micro 的 WPF 应用程序。
DataGrid 有一个属性 SelectedItem="{Binding Path=SelectedUsageRecord}"
如您所见,SelectedItem 绑定到 SelectedUsageRecord 属性。但我需要能够处理选择多个记录。这可以将多个记录绑定到集合属性吗?我没有看到像“SelectedItems”这样的东西......谢谢。
我有一个使用 Caliburn.Micro 的 WPF 应用程序。
DataGrid 有一个属性 SelectedItem="{Binding Path=SelectedUsageRecord}"
如您所见,SelectedItem 绑定到 SelectedUsageRecord 属性。但我需要能够处理选择多个记录。这可以将多个记录绑定到集合属性吗?我没有看到像“SelectedItems”这样的东西......谢谢。
这是我在遇到与您相同的情况后所做的事情。简而言之,直接处理选择更改事件并从事件参数中提取选定的行。假设“Rows”的源集合每个都是 RowViewModel,以及“_selectedRows”的集合。
<DataGrid RowsSource="{Binding Rows}" x:Name="Rows"
SelectionMode="Extended" SelectionUnit="FullRow">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cal:ActionMessage MethodName="SelectedRowsChangeEvent">
<cal:Parameter Value="$eventArgs" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
public void SelectedRowsChangeEvent(SelectionChangedEventArgs e)
{
foreach (var addedRow in e.AddedRows)
{
_selectedRows.Add(addedRow as RowViewModel);
}
foreach (var removedRow in e.RemovedRows)
{
_selectedRows.Remove(removedRow as RowViewModel);
}
}
我只是想发布我的解决方案。在 Caliburn micro 中,只要您遵守命名约定,就无需设置源。
Xaml
<DataGrid x:Name="Rows" SelectionMode="Extended" cal:Message.Attach="[Event SelectionChanged] = [Row_SelectionChanged($eventArgs)]">
C#
public List<MyObject> Rows { get; set; }
public MyObject SelectedRow { get; set; } //Will be set by Caliburn Micro. No need to use "SelectedItem={...}"
List<MyObject> _selectedObjects = new List<MyObject>();
public void Row_SelectionChanged(SelectionChangedEventArgs obj)
{
_selectedObjects.AddRange(obj.AddedItems.Cast<MyObject>());
obj.RemovedItems.Cast<MyObject>().ToList().ForEach(w => _selectedObjects.Remove(w));
}
此处发布的两种解决方案都可以正常工作,但由于“SelectionChangedEventArgs”属性,它们依赖于在您的视图模型中添加视图 (wpf) 程序集。如果您打算在不同平台上重用视图模型,我认为这对跨平台解决方案不利。
所以,我发布了我的解决方案,它更符合 MVVM 模式。我在这个例子中使用了syncfusion SfDataGrid,但这应该适用于普通的DataGrid:
首先我们需要扩展 DataGrid 类,所以我们创建了一个类。我将其命名为“CustomSfDataGrid.cs”。请注意,我还订阅了 SelectionChanged 事件,并且只是直接从“SelectedItems”属性获取数据。
using System.Windows;
using Caliburn.Micro;
using Syncfusion.UI.Xaml.Grid;
namespace DesktopClient.WPF.Controls
{
public class CustomSfDataGrid : SfDataGrid
{
///Bindable collection of objects property linked to the DependencyProperty called: "CustomSelectedItems"
///We can use "CustomSelectedItems" as a Binding Property in WPF
public BindableCollection<object> CustomSelectedItems
{
get
{
return (BindableCollection<object>)GetValue(CustomSelectedItemsProperty);
}
set
{
SetValue(CustomSelectedItemsProperty, value);
}
}
// Using a DependencyProperty as the backing store for SelectedItem. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CustomSelectedItemsProperty = DependencyProperty.Register("CustomSelectedItems", typeof(BindableCollection<object>), typeof(CustomSfDataGrid), new PropertyMetadata(null));
public CustomSfDataGrid()
{
SelectionChanged += CustomSfDataGrid_SelectionChanged;
}
private void CustomSfDataGrid_SelectionChanged(object sender, GridSelectionChangedEventArgs e)
{
this.CustomSelectedItems = new BindableCollection<object>(this.SelectedItems);
}
}
}
在 .xaml 文件中,我添加了一个名为“custom”的标头,它指向我的“CustomSfDataGrid.cs”的命名空间。然后,我将新的“CustomSelectedItems”属性绑定到“MyViewModelProperty”。最后,我正在使用“SelectionChanged”事件。
<UserControl
xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
xmlns:cal="http://www.caliburnproject.org"
xmlns:custom="clr-namespace:DesktopClient.WPF.Controls">
<Grid>
<custom:CustomSfDataGrid x:Name="dataGrid" ItemsSource="{Binding Models}"
SelectionMode="Extended" SelectionChanged="OnSelectionChanged"
CustomSelectedItems="{Binding MyViewModelProperty, Mode=OneWayToSource}">
<syncfusion:SfDataGrid.Columns>
<!-- Column Schema -->
</syncfusion:SfDataGrid.Columns>
</custom:CustomSfDataGrid>
</Grid>
最后,在 ViewModel 中我有一个“BindableCollection”属性。
using using System.Linq;
//
//...
private BindableCollection<object> _myViewModelProperty;
public BindableCollection<object> MyViewModelProperty
{
get
{
return _myViewModelProperty;
}
set
{
_myViewModelProperty = value;
}
}
//
public void UsingMyViewModel()
{
//cast the collection of objects to a different type using linq
BindableCollection<MyCastedType> x = new BindableCollection<BrandModel>(MyViewModelProperty.OfType<BrandModel>());
//alternative casting method
BindableCollection<MyCastedType> y = new BindableCollection<MyCastedType>();
foreach (var item in MyViewModelProperty)
{
y.Add(item as MyCastedType);
}
}