我有一个使用Caliburn.Micro的WPF应用程序。
DataGrid有一个属性SelectedItem =“{Binding Path = SelectedUsageRecord}”
如您所见,SelectedItem绑定到SelectedUsageRecord属性。但我需要能够处理选择多个记录。这可以将多个记录绑定到集合属性吗?我没有看到像“SelectedItems”这样的东西...... 感谢。
答案 0 :(得分:6)
这是我和你一样的情景后做的事情。简而言之,直接处理选择更改事件并从事件args中提取所选行。 假设“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);
}
}
答案 1 :(得分:4)
我只想发布我的解决方案。在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));
}
答案 2 :(得分:2)
此处发布的两个解决方案都可以正常工作,但是由于具有“ 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);
}
}