0

I have a WPF-App (.Net Framework 4.7.2.) with a DataGrid inside, where Projects are listed. I built the app by the MVVM-Concept, so I have a MainWindowViewModel, on this layer is my DataGrid. Then I have a ProjectsViewModel, inside there, there is a Property called SelectedProject, this is my currently selected Project. Inside the ProjectsViewModel, there is the ProjectViewModel, inside this ViewModel, there are all Properties needed, to fill my DataGrid with Data.

It all works just fine, but I do have one Problem...

If I want to unselect a Project, I have to select a other Project, by clicking on it. How can I unselect all Projects, for instance by clicking to the outside of the DataGrid, so my question is, is there any possible way, for unselecting all Items in a DataGrid, is there maybe an event, or something else?

Here is my DataGrid XAML Code:

<DataGrid x:Name="Data" x:Uid="Data" Margin="10,41,10,123" DataContext="{Binding Path=ProjectsViewModel}" ItemsSource="{Binding Path=Projects}" SelectedItem="{Binding Path=SelectedProject}" AutoGenerateColumns="False" IsEnabled="{Binding Path=IsEditable}">
                <DataGrid.RowStyle>
                    <Style TargetType="DataGridRow">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=IsCheckedIn}" Value="true">
                                <Setter Property="Background" Value="LightGreen"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=IsCheckedIn}" Value="false">
                                <Setter Property="Background" Value="Transparent"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </DataGrid.RowStyle>
                <DataGrid.Columns>
                    <DataGridTextColumn x:Name="GridHeadProjectNumber" x:Uid="GridHeadProjectNumber" Header="Projekt" Binding="{Binding Path=IssueKey}" IsReadOnly="True">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="TextBlock">
                                <Setter Property="HorizontalAlignment" Value="Center"/>
                                <Setter Property="Margin" Value="2,0,2,0"/>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTextColumn x:Name="GridHeadTitle" x:Uid="GridHeadTitle" Header="Titel" Binding="{Binding Path=Summary}" IsReadOnly="True"/>
                    <DataGridTextColumn x:Name="GridHeadStatus" x:Uid="GridHeadStatus" Header="Status" Binding="{Binding Path=Status}" IsReadOnly="True"/>
                    <DataGridTextColumn x:Name="GridHeadTimeSpent" x:Uid="GridHeadTimeSpent" Header="Bisher gearbeitete Zeit" Binding="{Binding Path=TimeSpent}" IsReadOnly="True"/>
                    <DataGridTextColumn x:Name="GridHeadDueDate" x:Uid="GridHeadDueDate" Header="Fälligkeit" Binding="{Binding Path=DueDate, StringFormat={}{0:dd.MM.yyyy HH:mm}}" IsReadOnly="True"/>
                    <DataGridTextColumn x:Name="GridHeadLastCheckIn" x:Uid="GridHeadLastCheckIn" Header="Letzter Checkin" Binding="{Binding Path=LastCheckIn, StringFormat={}{0:dd.MM.yyyy HH:mm}}" IsReadOnly="True"/>
                    <DataGridTemplateColumn x:Name="GridButtonCheckIn" x:Uid="GridButtonCheckIn" Header="CheckIn" >
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button Name="btnCheckIn" Uid="btnCheckIn" Content="{Binding Path=CheckInOutText}" Command="{Binding Path=CheckInCommand}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn x:Name="GridButtonOpenInBrowser" x:Uid="GridButtonOpenInBrowser" Header="Öffnen" >
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button Name="btnOpenInBrowser" Uid="btnOpenInBrowser" Content="Öffnen" Command="{Binding Path=OpenInBrowserCommand}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>

Here is my SelectedProject Property inside the ProjectsViewModel:

public ProjectViewModel SelectedProject
        {
            get => _selectedProject;
            set
            {
                _selectedProject = value;
                NotifyPropertyChanged(nameof(SelectedProject));
                CheckInSelectedProjectCommand.NotifyCanExecuteChanged();
                OpenSelectedProjectCommand.NotifyCanExecuteChanged();
                // Minimize()
            }
        }

And here is my ProjectViewModel Class:

public partial class ProjectViewModel : ViewModelBase
    {
        private readonly IJiraManager _jiraManager;
        private readonly IProjectWorkflow _projectWorkflow;
        private readonly IBroker _broker;
        private Action _checkOutAllProjects;
        private readonly IWindow _window;
        private readonly SettingsViewModel _settingsViewModel;
        private readonly TaskbarViewModel _taskbarViewModel;
        private Project _project;
        private bool _isCheckedIn = false;
        private DateTime? _currentCheckIn;

        public ProjectViewModel(IJiraManager jiraManager, IProjectWorkflow projectWorkflow, Project project, Action checkOutAllProjects, IWindow window, SettingsViewModel settingsViewModel, IBroker broker, TaskbarViewModel taskbarViewModel, IDateTimeProvider dateTimeProvider)
        {
            this.InitializeCommands();
            _jiraManager = jiraManager ?? throw new ArgumentNullException(nameof(jiraManager));
            _project = project ?? throw new ArgumentNullException(nameof(project));
            _checkOutAllProjects = checkOutAllProjects ?? throw new ArgumentNullException(nameof(checkOutAllProjects));
            _window = window ?? throw new ArgumentNullException(nameof(window));
            _settingsViewModel = settingsViewModel ?? throw new ArgumentNullException(nameof(settingsViewModel));
            _broker = broker ?? throw new ArgumentNullException(nameof(broker));
            _taskbarViewModel = taskbarViewModel ?? throw new ArgumentNullException(nameof(taskbarViewModel));
            _projectWorkflow = projectWorkflow ?? throw new ArgumentNullException(nameof(projectWorkflow));
            _dateTimeProvider = dateTimeProvider ?? throw new ArgumentNullException(nameof(dateTimeProvider));
        }
 
        public bool IsCheckedIn
        {
            get => _isCheckedIn;
            set
            {
                _isCheckedIn = value;
                NotifyPropertyChanged(nameof(IsCheckedIn));
                NotifyPropertyChanged(nameof(CheckInOutText));
                if (value)
                {
                    _broker.Publish(this, new ProjectCheckInMessage(this));
                }
                if (_settingsViewModel.MinimizeAfterCheckIn)
                {
                    _window.Minimize();
                }
            }
        }
        public DateTime? CurrentCheckIn { get { return _currentCheckIn; } set { _currentCheckIn = value; } }
        public string Summary { get => _project.Summary; }
        public string Status { get => _project.Status; }
        public string IssueKey { get => _project.IssueKey; }
        public string TimeSpent { get => _project.TimeSpent; }
        public DateTime? DueDate { get => _project.DueDate; }
        public DateTime? LastCheckIn { get => _project.LastCheckIn; }
        public string CheckInOutText { get => IsCheckedIn ? "Check Out" : "Check In"; }
    }

I hope you can help me :)

Jakob
  • 9
  • 3
  • What happens when you set the `SelectedProject` to null? It should unselect the selected project. You can check the LostFocus event of data grid to put the code when data grid focus is moved out. – user1672994 Aug 16 '21 at 05:34
  • If your question is how the user have to unselect items, then it's a ctrl-click in list controls (not sure about `DataGrid`, try it). But sure you can make your own way: button to unselect all, handling clicks outside of controls client area, etc. – Sinatr Aug 16 '21 at 06:57

1 Answers1

0

UPDATE: I used the LostFocus Event and Binded it to a porperty named IsProjectSelected, if the event gets triggered i Check if a ProjectIsSelected, if a Project is selected i unselect it. Here is my Code:

Eventhandler:

LostFocus += MainWindowViewModel.ProjectsViewModel.DataGrid_LostFocus;

EventMethod:

public void DataGrid_LostFocus(object sender, RoutedEventArgs e)
        {
            if(IsProjectSelected)
            {
                IsProjectSelected = false;
            }
        }

In the setter of the SelectedProject Property I set the value of IsSelectedProject;:

public ProjectViewModel SelectedProject
        {
            get => _selectedProject;
            set
            {
                _selectedProject = value;
                NotifyPropertyChanged(nameof(SelectedProject));
                CheckInSelectedProjectCommand.NotifyCanExecuteChanged();
                OpenSelectedProjectCommand.NotifyCanExecuteChanged();
                IsProjectSelected = true;
                // Minimize()
            }
        }
Jakob
  • 9
  • 3
  • Why do you need `IsProjectSelected` property? Just set `SelectedProject = null` from lost focus event. Btw, subscribing view model to view events is not pure MVVM, see [this topic](https://stackoverflow.com/q/1048517/1997232) how to do it properly, e.g. with event command abstraction. – Sinatr Aug 16 '21 at 06:59
  • Because, I need SelectedProject in my MainViewModel, so if I set it to zero when the event is triggered, I can't checkIn to a Project with a Button in the MainWindowViewModel – Jakob Aug 16 '21 at 09:28