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
. 를 캡슐화했습니다.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"
선택된ItemsCommand는 뷰 모델에 기록되는 ICommand 유형입니다.
사용된 DLL:
System.Windows.Interactivity.dll
디폴트 설정DataGrid
WPF에서는 바인딩을 사용할 수 없습니다.SelectedItem
- Property, 원인:SelectedItems
Property가 DependencyProperty가 아닙니다.
원하는 것을 얻기 위한 한 가지 방법은SelectionChanged
- 선택한 항목을 저장하는 ViewModel 속성을 업데이트하는 DataGrid 이벤트.
선택한 속성DataGrid의 항목은 IList 유형이므로 목록의 항목을 특정 유형으로 캐스팅해야 합니다.
C#
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;}
}
선택 가능한 클래스의 일반 기본 클래스를 만듭니다.이노티파이PropertyChanged는 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));
데이터 그리드에 바인딩하고 MySelected의 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;
[Edit] : : > [ Enable Row Virtualization ]가 true이면 동작하지 않는 것 같습니다.
WPF 데이터 그리드, WPF 데이터 그리드Data Grid data data data 。Rows.SelectionMode § DataGrid.Rows. §을 각각" 및 "합니다."확장" "CellOrowHeader" "CellOrowHeader" 입니다.블렌드사용자는 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>
...
제 솔루션은 Sandesh와 거의 비슷합니다.한편, 저는 이 문제를 해결하기 위해 Custom Data Grid를 사용하지 않았습니다.대신 뷰 모델에서 적절한 기능을 가진 플러스 버튼 클릭 이벤트를 사용했습니다.제 코드에서 중요한 점은 데이터그리드 위치에서 여러 사용자 개체를 삭제할 수 있는 것이 PeopleList 속성(ObservableCollection)에 바인딩되어 있다는 것입니다.
이것은 나의 모델입니다.
public class Person
{
public Person()
{
}
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
}
이것은 내 View Model입니다(필요한 부품만 해당).
public class PersonViewModel : BindableBase
{
private ObservableCollection<Person> _peopleList;
// to be able to delete or save more than one person object
private List<Person> _selectedPersonList;
//MyICommand
public MyICommand AddCommand { get; set; }
public MyICommand DeleteCommand { get; set; }
private string _firstName;
private string _lastName;
private int _age;
public PersonViewModel()
{
_peopleList = new ObservableCollection<Person>();
LoadPerson();
AddCommand = new MyICommand(AddPerson);
DeleteCommand = new MyICommand(DeletePerson, CanDeletePerson);
// To be able to delete or save more than one person
_selectedPersonList = new List<Person>();
}
public ObservableCollection<Person> PeopleList
{
get { return _peopleList; }
set
{
_peopleList = value;
RaisePropertyChanged("PeopleList");
}
}
public List<Person> SelectedPersonList
{
get { return _selectedPersonList; }
set
{
if (_selectedPersonList != value)
{
RaisePropertyChanged("SelectedPersonList");
}
}
}
private void DeletePerson()
{
// to be able to delete more than one person object
foreach (Person person in SelectedPersonList)
{
PeopleList.Remove(person);
}
MessageBox.Show(""+SelectedPersonList.Count); // it is only a checking
SelectedPersonList.Clear(); // it is a temp list, so it has to be cleared after the button push
}
public void GetSelectedPerson(DataGrid datagrid)
{
IList selectedItems = datagrid.SelectedItems;
foreach (Person item in selectedItems)
{
SelectedPersonList.Add(item);
}
}
마이뷰(xmal):
<UserControl x:Class="DataBase.Views.PersonView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DataBase.Views"
xmlns:viewModel="clr-namespace:DataBase.ViewModels" d:DataContext="{d:DesignInstance Type=viewModel:PersonViewModel}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" Background="AliceBlue">
<TextBlock Text="First Name:"/>
<TextBox x:Name="firstNameTxtBox" Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="Last Name:"/>
<TextBox x:Name="lastNameTxtBox" Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="Age:"/>
<TextBox x:Name="ageTxtBox" Text="{Binding Age}"/>
<TextBlock Text="{Binding FullName}"/>
<Button Content="Add" IsEnabled="{Binding CanAddPerson}" Command="{Binding AddCommand}"/>
<Button Content="Delete" Command="{Binding DeleteCommand}" Click="Delete_Click"/>
<DataGrid x:Name="datagridPeopleList" ItemsSource="{Binding PeopleList}" AutoGenerateColumns="True" SelectedItem="{Binding SelectedPerson}" SelectionMode="Extended" SelectionUnit="FullRow"/>
<!--<ListView Height="50" ItemsSource="{Binding PeopleList}" SelectedItem="{Binding SelectedPerson}" Margin="10">
</ListView>-->
</StackPanel>
</Grid>
</UserControl>
마이뷰(.cs):
public partial class PersonView : UserControl
{
public PersonViewModel pvm;
public PersonView()
{
pvm = new PersonViewModel();
InitializeComponent();
DataContext = pvm;
}
private void Delete_Click(object sender, RoutedEventArgs e)
{
pvm.GetSelectedPerson(datagridPeopleList);
}
}
세계 최악의 (고상하지 않은) 솔루션이 아니라 유용하기를 바랍니다:D
언급URL : https://stackoverflow.com/questions/22868445/select-multiple-items-from-a-datagrid-in-an-mvvm-wpf-project
'programing' 카테고리의 다른 글
임시 테이블에 데이터 삽입 (0) | 2023.04.11 |
---|---|
소수점 두 자리만 표시되도록 플로트 만들기 (0) | 2023.04.11 |
WooCommerce - 제품 페이지 카테고리 가져오기 (0) | 2023.04.06 |
Ninja 폼 데이터로 페이지 작성 (0) | 2023.04.06 |
동일한 데이터베이스 내에서 컬렉션을 가장 빨리 복사할 수 있는 방법은 무엇입니까? (0) | 2023.04.06 |