J'ai une grille de données remplie d'éléments et une case à cocher pour chaque élément. Je cherche un moyen de faire en sorte qu'un objet de mon ViewModel soit l'élément dont la case à cocher est actuellement cochée.
Voici mon XAML jusqu'à présent :
<Window x:Class="fun_with_DataGridCheckBoxColumns.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:fun_with_DataGridCheckBoxColumns"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
<Label Content="Chosen One : " />
<Label Content="{Binding ChosenOne.Name, Mode=OneWay}" />
</StackPanel>
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ID, Mode=OneWay}" IsReadOnly="True"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=OneWay}" IsReadOnly="True"/>
<DataGridCheckBoxColumn Header="Is Chosen"/>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
et mon CS :
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace fun_with_DataGridCheckBoxColumns
{
public partial class MainWindow : Window
{
public Person ChosenOne { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = new Viewmodel();
}
}
public class Viewmodel : INotifyPropertyChanged
{
public ObservableCollection<Person> People { get; private set; }
private Person _chosenOne = null;
public Person ChosenOne
{
get
{
if (_chosenOne == null) { return new Person { Name = "Does Not Exist" }; }
else return _chosenOne;
}
set
{
_chosenOne = value;
NotifyPropertyChanged("ChosenOne");
}
}
public Viewmodel()
{
People = new ObservableCollection<Person>
{
new Person { Name = "John" },
new Person { Name = "Marie" },
new Person { Name = "Bob" },
new Person { Name = "Sarah" }
};
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Person
{
private static int person_quantity = 0;
private int _id = ++person_quantity;
public int ID { get { return _id; } }
public string Name { get; set; }
}
}
Voici le comportement que je recherche :
- ChosenOne dans ViewModel devient la personne dont la case est cochée.
- Lorsqu'une case est cochée, toutes les autres ne le sont pas.
- Si aucune case n'est cochée, ChosenOne prend la valeur null.
En fait, c'est le même comportement que si j'avais mis cela dans le DataGrid (XAML) :
SelectedItem="{Binding ChosenOne, Mode=TwoWay}"
Mais dans mon cas, ChosenOne ne peut pas être le SelectedItem de la grille de données car j'ai besoin de SelectedItem pour autre chose, et je dois utiliser des cases à cocher pour des raisons de société.
Je n'ai pas trouvé comment simuler cette logique "SelectedItem" avec des cases à cocher.
Je sais que je pourrais mettre une propriété "bool IsChosen" dans ma classe Person et lier la case à cocher à cette propriété, mais je préférerais vraiment éviter cela. Ce sera ma solution si tout le reste échoue.
Merci.