2

I've created a DataGrid that is using AutoGeneratedColumns. Everything works as expected with the exception of the Checkbox column. When the checkbox is clicked, the data source is not updated. It seems the DataGrid needs to lose focus before the data source is updated. Is there an easy way around this, or do I need to generate the columns manually?

Xaml:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="25" />
        <RowDefinition Height="*" />
        <RowDefinition Height="5" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem x:Name="moNewSystem" Header="_New System" Click="moNewSystem_Click" />
                <MenuItem x:Name="moSaveSystems" Header="_Save Systems" Click="moSaveSystems_Click" />
                <MenuItem x:Name="moLoadSystems" Header="_Load Systems" Click="moLoadSystems_Click" />
                <Separator />
                <MenuItem x:Name="moExit" Header="E_xit" Click="moExit_Click" />
            </MenuItem>
        </Menu>
    </DockPanel>

    <DataGrid x:Name="dgvSystems" Grid.Row="1" ItemsSource="{Binding AllSystems, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AutoGeneratingColumn="dgvSystems_AutoGeneratingColumn" />
    <GridSplitter Grid.Row="2" VerticalAlignment="Stretch" />
    <ListBox x:Name="lstOutput" Grid.Row="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    
</Grid>

View Model:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    private ObservableCollection<Systems> allSystems = new ObservableCollection<Systems>();
    public ObservableCollection<Systems> AllSystems 
    { 
        get { return allSystems; }
        set { allSystems = value; OnPropertyChanged(); }
    }
}

public class Systems : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        private MainWindow Parent;

        private string symbol;
        public string Symbol
        {
            get { return symbol; }
            set { symbol = value; OnPropertyChanged(); }
        }

        private bool isEnabled;
        public bool IsEnabled
        {
            get { return isEnabled; }
            set 
            { 
                isEnabled = value;
                OnPropertyChanged();

                if (isEnabled)
                    StartSystem();
                else StopSystem();
            }
        }

        private void StartSystem()
        {
            Parent.Log("Started");
        }

        private void StopSystem()
        {
            Parent.Log("Stopped");
        }

        public Systems(MainWindow parent)
        {
            Parent = parent;
        }
    }

Window:

public partial class MainWindow : Window
    {
        public ViewModel viewModel = new ViewModel();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            DataContext = viewModel;

            foreach (var column in dgvSystems.Columns)
                column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
        }

        private void moNewSystem_Click(object sender, RoutedEventArgs e)
        {
            NewSystem nsWindow = new NewSystem(this);
            bool? result = nsWindow.ShowDialog();
            switch(result)
            {
                case true:
                    // Add System to collection
                    viewModel.AllSystems.Add(nsWindow.ThisSystem);
                    nsWindow.Close();
                    break;
            }
        }

        private void moSaveSystems_Click(object sender, RoutedEventArgs e)
        {

        }

        private void moLoadSystems_Click(object sender, RoutedEventArgs e)
        {

        }

        private void moExit_Click(object sender, RoutedEventArgs e)
        {

        }

        public void Log(string message)
        {
            string text = string.Format("{0}: {1}", DateTime.Now, message);
            lstOutput.Items.Insert(0, text);
        }
    }
6
  • You should also share your code-behind, in case you're doing something with MouseLeftButtonUp that is interfering with updating the DataGrid's CheckBox column. Commented Aug 25, 2021 at 23:43
  • Edited to include the additional code. Commented Aug 26, 2021 at 0:17
  • 1
    Am I blind, or is the method 'dgvSystems_MouseLeftButtonUp' missing in codebehind? Does the compiler not moan about is? Commented Aug 26, 2021 at 6:08
  • Just a word about convention: your class Systems is actually one system. So naming it as plural could be misleading. To avoid conflict with the System Namespace, you may find a better name for your type :-) Commented Aug 26, 2021 at 6:11
  • Thanks dba. You are correct about the dgvSystems_MouseLeftButtonUp. I simplified the code before posting and forgot to remove that. I have edited the code accordingly. Commented Aug 26, 2021 at 17:27

1 Answer 1

1

This link might provide the some of the answer for you -> https://stackoverflow.com/a/15907332/16052620

The only change, is to set the binding 'UpdateSourceTrigger' property to PropertyChanged.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.