使用Caliburn.Micro在DataGrid中选择多个记录

时间:2012-05-23 14:14:14

标签: wpf caliburn.micro

我有一个使用Caliburn.Micro的WPF应用程序。

DataGrid有一个属性SelectedItem =“{Binding Path = SelectedUsageRecord}”

如您所见,SelectedItem绑定到SelectedUsageRecord属性。但我需要能够处理选择多个记录。这可以将多个记录绑定到集合属性吗?我没有看到像“SelectedItems”这样的东西...... 感谢。

3 个答案:

答案 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);
            }
        }