4

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

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

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

4

3 回答 3

6

这是我在遇到与您相同的情况后所做的事情。简而言之,直接处理选择更改事件并从事件参数中提取选定的行。假设“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);
    }
}
于 2012-11-01T02:04:42.010 回答
5

我只是想发布我的解决方案。在 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));
}
于 2017-01-10T07:24:55.300 回答
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);
            }
        }
于 2018-11-20T04:30:13.620 回答