C# WPF 将 GridData 中的 CheckBox 绑定到基础数组,数据未更改

C# WPF Binding CheckBox in GridData to underlying Array, data not changed

对 WPF 非常陌生。将 CheckBox 绑定到基础数组数据时出现问题。该值在数据启动时设置,但检查它不会导致基础数据发生更改。请注意,我已经实现了复选框以允许选择多个项目。另请注意,我已经验证这不是因为焦点(复选框必须失去焦点),因为我在点击检查基础数据的 "migrate" 按钮之前点击了其他东西。我确定我错过了一些自动装配的魔法,但我已经查看了大量其他博客但没有成功。

无效的复选框是:

       <DataGridTemplateColumn Width="60" Header="Migrate">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding Checked}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

代码很简单,MainWindow.xaml:

<Window x:Class="FFFJsonMigrator.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:Code="clr-namespace:FFFJsonMigrator.Code"
        mc:Ignorable="d"
        Title="JSON Migrator" Height="482" Width="729">
    <Grid Background="#FF9DB2C1" Margin="0,0,2,-21">
        <Grid.DataContext>
            <Code:FFFJsonMigrator/>
        </Grid.DataContext>
        <DataGrid x:Name="dataGrid"  ItemsSource="{Binding myAccountList}" SelectionMode="Extended" HorizontalAlignment="Left" Margin="10,63,0,0" VerticalAlignment="Top" Height="352" Width="685" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserSortColumns="False" HeadersVisibility="Column" AlternatingRowBackground="#FFE7F3FA" AlternationCount="1" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" ColumnWidth="Auto" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="60" Header="Migrate">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding Checked}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Binding="{Binding Id}" IsReadOnly="True"  Header="Id" Width="40"/>
                <DataGridTextColumn Binding="{Binding AccountName}" IsReadOnly="True"  Header="Account Name" Width="250"/>
                <DataGridTextColumn Binding="{Binding Forms}"  IsReadOnly="True"  Header="Forms" Width="60"/>
                <DataGridTextColumn Binding="{Binding Pending}"  IsReadOnly="True"  Header="Pending"  Width="60"/>
                <DataGridTextColumn Binding="{Binding Archived}" IsReadOnly="True"   Header="Archived"  Width="60"/>
                <DataGridTextColumn Binding="{Binding Total}"  IsReadOnly="True"  Header="Total"  Width="60"/>
            </DataGrid.Columns>
        </DataGrid>
        <ComboBox x:Name="envComboBox" HorizontalAlignment="Left" Margin="10,32,0,0" VerticalAlignment="Top" Width="120"/>
        <Button x:Name="refreshButton" Content="Refresh" HorizontalAlignment="Left" Margin="144,32,0,0" VerticalAlignment="Top" Width="75"/>
        <CheckBox x:Name="activeOnlyCheckbox" Content="Active Accounts Only" HorizontalAlignment="Left" Margin="14,427,0,0" VerticalAlignment="Top"/>
        <Button x:Name="migrateButton" Command="{Binding MigrateCommand}" IsEnabled="True" Content="Migrate Forms" HorizontalAlignment="Left" Margin="506,424,0,0" VerticalAlignment="Top" Width="75"/>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="236,10,0,0" TextWrapping="Wrap" Text="Select the accounts to be migrated. The JSON in the Form, FormArchive and FormPending tables will be copied to Azure and the path to the file added to the JsonPath columns" VerticalAlignment="Top" Width="353"/>
    </Grid>
</Window>

FFFJsonMigrator.cs :

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace FFFJsonMigrator.Code
{
    public class FFFJsonMigrator : INotifyPropertyChanged
    {
        public ObservableCollection<AccountData> myAccountList { get; set; }

        public FFFJsonMigrator()
        {
            myAccountList = new ObservableCollection<AccountData>();
            myAccountList.Add(new AccountData(false, "Test1", 1232344, 2, 3, 4, 9));
            myAccountList.Add(new AccountData(false, "Test2", 2222345, 1, 1, 1, 3)); ;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private void MigrateMessage()
        {
            if (IsAnyToMigrate())
            {
                // Configure the message box to be displayed
                string messageBoxText = "Qre you sure you want to Migrate the selected Account JSON files?";
                string caption = "Migrate Json Files for Selected Accounts";
                MessageBoxButton button = MessageBoxButton.YesNo;
                MessageBoxImage icon = MessageBoxImage.Warning;

                // Display message box
                MessageBoxResult result = MessageBox.Show(messageBoxText, caption, button, icon);

                if (result == MessageBoxResult.Yes)
                {
                    ExecuteMigrate();
                }
            }
            else
            {
                // Configure the message box to be displayed
                string messageBoxText = "You have not chosen any accounts to migrate. Please select one or more Accounts to migrate.";
                string caption = "No Accounts To Migrate";
                MessageBoxButton button = MessageBoxButton.OK;
                MessageBoxImage icon = MessageBoxImage.Warning;

                // Display message box
                MessageBox.Show(messageBoxText, caption, button, icon);
            }

        }

        public bool IsAnyToMigrate()
        {
            foreach (AccountData accnt in myAccountList)
            {
                if (accnt.Checked)
                    return true;

            }
            return false;
        }

        private ICommand _migrateCommand;
        public ICommand MigrateCommand
        {
            get
            {
                return _migrateCommand ?? (_migrateCommand = new CommandHandler(() => MigrateMessage(), true));
            }
        }

        public class CommandHandler : ICommand
        {
            private Action _action;
            private bool _canExecute;
            public CommandHandler(Action action, bool canExecute)
            {
                _action = action;
                _canExecute = canExecute;
            }

            public bool CanExecute(object parameter)
            {
                return _canExecute;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                _action();
            }
        }
    }

    public class AccountData
    {
        public AccountData(bool check, string accountName, int id, int forms, int pending, int archived, int total)
        {
            AccountName = accountName;
            Id = id;
            Forms = forms;
            Pending = pending;
            Archived = archived;
            Total = total;
            Checked = check;
        }

        public bool Checked { get; set; }
        public string AccountName { get; set; }
        public int Id { get; set; }
        public int Forms { get; set; }
        public int Pending { get; set; }
        public int Archived { get; set; }
        public int Total { get; set; }
    }
}

最后,实际的 window 本身。请注意,我正在检查然后点击 "Migrate" 按钮...

您应该在 class AccoutData 中实现 INotifyPropertyChanged,以便源或目标中的任何更改都是同步的。

    public class AccountData : INotifyPropertyChanged
    {
        public AccountData(bool check, string accountName, int id, int forms, int pending, int archived, int total)
        {
            AccountName = accountName;
            Id = id;
            Forms = forms;
            Pending = pending;
            Archived = archived;
            Total = total;
            Checked = check;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        ........
        .........  
    }