MVVM WPF 프로젝트의 DataGrid에서 여러 항목 선택
DataGrid
MVVM WPF 프로젝트에서 여러 항목을 어떻게 선택할 수 있습니까?
이렇게 하려면 사용자 지정 종속성 속성 을 추가하기 만하면됩니다 .
public class CustomDataGrid : DataGrid
{
public CustomDataGrid ()
{
this.SelectionChanged += CustomDataGrid_SelectionChanged;
}
void CustomDataGrid_SelectionChanged (object sender, SelectionChangedEventArgs e)
{
this.SelectedItemsList = this.SelectedItems;
}
#region SelectedItemsList
public IList SelectedItemsList
{
get { return (IList)GetValue (SelectedItemsListProperty); }
set { SetValue (SelectedItemsListProperty, value); }
}
public static readonly DependencyProperty SelectedItemsListProperty =
DependencyProperty.Register ("SelectedItemsList", typeof (IList), typeof (CustomDataGrid), new PropertyMetadata (null));
#endregion
}
이제 dataGrid
XAML에서 이것을 사용할 수 있습니다 .
<Window x:Class="DataGridTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:DataGridTesting.CustomDatagrid"
Title="MainWindow"
Height="350"
Width="525">
<DockPanel>
<local:CustomDataGrid ItemsSource="{Binding Model}"
SelectionMode="Extended"
AlternatingRowBackground="Aquamarine"
SelectionUnit="FullRow"
IsReadOnly="True"
SnapsToDevicePixels="True"
SelectedItemsList="{Binding TestSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DockPanel>
</Window>
내 ViewModel
:
public class MyViewModel : INotifyPropertyChanged
{
private static object _lock = new object ();
private List<MyModel> _myModel;
public IEnumerable<MyModel> Model { get { return _myModel; } }
private IList _selectedModels = new ArrayList ();
public IList TestSelected
{
get { return _selectedModels; }
set
{
_selectedModels = value;
RaisePropertyChanged ("TestSelected");
}
}
public MyViewModel ()
{
_myModel = new List<MyModel> ();
BindingOperations.EnableCollectionSynchronization (_myModel, _lock);
for (int i = 0; i < 10; i++)
{
_myModel.Add (new MyModel
{
Name = "Test " + i,
Age = i * 22
});
}
RaisePropertyChanged ("Model");
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged (string propertyName)
{
var pc = PropertyChanged;
if (pc != null)
pc (this, new PropertyChangedEventArgs (propertyName));
}
}
내 모델 :
public class MyModel
{
public string Name { get; set; }
public int Age { get; set; }
}
마지막으로 다음 코드는 MainWindow
다음 과 같습니다.
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
this.DataContext = new MyViewModel ();
}
}
이 깨끗한 MVVM 디자인이 도움이되기를 바랍니다.
내가 뭘 할 것은 만드는 것입니다 Behaviors
사용 System.Windows.Interactivity
. 프로젝트에서 수동으로 참조해야합니다.
SelectedItems
예를 들어 (ListBox, DataGrid) 노출하지 않는 컨트롤이 주어지면
다음과 같은 행동 클래스를 만들 수 있습니다.
public class ListBoxSelectedItemsBehavior : Behavior<ListBox>
{
protected override void OnAttached()
{
AssociatedObject.SelectionChanged += AssociatedObjectSelectionChanged;
}
protected override void OnDetaching()
{
AssociatedObject.SelectionChanged -= AssociatedObjectSelectionChanged;
}
void AssociatedObjectSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var array = new object[AssociatedObject.SelectedItems.Count];
AssociatedObject.SelectedItems.CopyTo(array, 0);
SelectedItems = array;
}
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IEnumerable), typeof(ListBoxSelectedItemsBehavior),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public IEnumerable SelectedItems
{
get { return (IEnumerable)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
}
그리고 당신에 XAML
내가 할 일 것이다 Binding
곳과 같은 i
것입니다 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
및 behaviors
당신의 네임 스페이스 Behavior
클래스를
<ListBox>
<i:Interaction.Behaviors>
<behaviors:ListBoxSelectedItemsBehavior SelectedItems="{Binding SelectedItems, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
당신의 가정하면 DataContext
에 대한이 ListBox
이 SelectedItems
재산 ViewModel
후 자동으로 업데이트됩니다 SelectedItems
. ie 에서 event
구독을 캡슐화했습니다 View
.
<ListBox SelectionChanged="ListBox_SelectionChanged"/>
원하는 경우 Behavior
클래스 유형을 변경할 수 있습니다 DataGrid
.
내 앱에서이 솔루션을 사용합니다.
XAML :
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectItemsCommand}" CommandParameter="{Binding Path=SelectedItems,ElementName=TestListView}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
xaml 파일 맨 위에 다음 코드 줄을 추가합니다.
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
SelectedItemsCommand는 뷰 모델에 작성된 ICommand 유형입니다.
사용 된 DLL :
System.Windows.Interactivity.dll
DataGrid
WPF 의 기본값 을 사용하면 SelectedItem
-Property에서 가능하므로 Binding을 사용할 수 SelectedItems
없습니다. -Property가 DependencyProperty가 아니기 때문입니다.
원하는 작업에 대한 한 가지 방법 SelectionChanged
은 선택한 항목을 저장하는 ViewModel의 속성을 업데이트하기 위해 DataGrid 의 -Event 를 등록하는 것 입니다.
DataGrid의 SelectedItems 속성 은 IList 유형이므로 목록의 항목을 특정 유형으로 캐스팅해야합니다.
씨#
public MyViewModel {
get{
return this.DataContext as MyViewModel;
}
}
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) {
// ... Get SelectedItems from DataGrid.
var grid = sender as DataGrid;
var selected = grid.SelectedItems;
List<MyObject> selectedObjects = selected.OfType<MyObject>().ToList();
MyViewModel.SelectedMyObjects = selectedObjects;
}
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid
SelectionChanged="DataGrid_SelectionChanged"
/>
</Grid>
</Window>
모델에 "IsSelected"속성을 추가하고 행에 체크 박스를 추가 할 수 있습니다.
재사용 가능한 일반 기본 클래스를 만들 수 있습니다 . 이렇게하면 코드와 UI 모두에서 행을 선택할 수 있습니다 .
이것은 내가 선택할 수있는 예제 클래스입니다.
public class MyClass
{
public string MyString {get; set;}
}
선택 가능한 클래스에 대한 일반 기본 클래스를 만듭니다. INotifyPropertyChanged는 IsSelected를 설정할 때 UI를 업데이트합니다.
public class SelectableItem<T> : System.ComponentModel.INotifyPropertyChanged
{
public SelectableItem(T item)
{
Item = item;
}
public T Item { get; set; }
bool _isSelected;
public bool IsSelected {
get {
return _isSelected;
}
set {
if (value == _isSelected)
{
return;
}
_isSelected = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("IsSelected"));
}
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
}
선택 가능한 클래스 만들기
public class MySelectableItem: SelectableItem<MyClass>
{
public MySelectableItem(MyClass item)
:base(item)
{
}
}
바인딩 할 속성 만들기
ObservableCollection<MySelectableItem> MyObservableCollection ...
속성 설정
MyObservableCollection = myItems.Select(x => new MySelectableItem(x));
DataGrid에 바인딩하고 MySelectedItem의 IsSelected 속성에 바인딩하는 DataGridRow에 스타일을 추가합니다.
<DataGrid
ItemsSource="{Binding MyObservableCollection}"
SelectionMode="Extended">
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</DataGrid.Resources>
</DataGrid>
선택한 행 / 항목을 가져 오려면
var selectedItems = MyObservableCollection.Where(x=>x.IsSelected).Select(y=>y.Item);
행 / 항목을 선택하려면
MyObservableCollection[0].IsSelected = true;
편집 ———> EnableRowVirtualization이 true 일 때 작동하지 않는 것 같습니다.
WPF DataGrid는 이것을 허용합니다. DataGrid.Rows.SelectionMode 및 DataGrid.Rows.SelectionUnit을 각각 "Extended"및 "CellOrRowHeader"로 설정하기 만하면됩니다. 이것은 내가 포함 된 이미지에서 볼 수 있듯이 Blend에서 할 수 있습니다. 이렇게하면 사용자가 Shift 또는 Ctrl 키를 사용하여 원하는만큼 각 셀, 전체 행 등을 선택할 수 있습니다.
내가 작업중인 프로젝트는 MVVM Light 를 사용 하며이 블로그 게시물이 가장 간단한 솔루션이라는 것을 알았 습니다 . 여기에서 솔루션을 반복하겠습니다.
모델보기 :
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
...
public class SomeVm : ViewModelBase {
public SomeVm() {
SelectItemsCommand = new RelayCommand<IList>((items) => {
Selected.Clear();
foreach (var item in items) Selected.Add((SomeClass)item);
});
ViewCommand = new RelayCommand(() => {
foreach (var selected in Selected) {
// todo do something with selected items
}
});
}
public List<SomeClass> Selected { get; set; }
public RelayCommand<IList> SelectionChangedCommand { get; set; }
public RelayCommand ViewCommand { get; set; }
}
XAML :
<Window
...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:command="http://www.galasoft.ch/mvvmlight"
...
<DataGrid
Name="SomeGrid"
...
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<command:EventToCommand
Command="{Binding SelectionChangedCommand}"
CommandParameter="{Binding SelectedItems, ElementName=SomeGrid}" />
</i:EventTrigger>
</i:Interaction.Triggers>
...
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="View" Command="{Binding ViewCommand}" />
</ContextMenu>
</DataGrid.ContextMenu>
...
ReferenceURL : https://stackoverflow.com/questions/22868445/select-multiple-items-from-a-datagrid-in-an-mvvm-wpf-project
'Programing' 카테고리의 다른 글
Python : 목록에서 빈 목록을 제거하는 방법? (0) | 2020.12.28 |
---|---|
malloc () 대 HeapAlloc () (0) | 2020.12.28 |
Rubocop 25 라인 블록 크기 및 RSpec 테스트 (0) | 2020.12.28 |
WPF의 목록 상자 항목을 선택할 수 없도록 설정 (0) | 2020.12.28 |
: focus를 사용하여 외부 div 스타일을 지정합니까? (0) | 2020.12.28 |