0
votes

I'm working with a DataGrid in WPF and I'm trying to perform some data binding that it a little more complex than I'm used to. I have an ObservableCollection of a class that also implements an ObservableCollection of a subclass. I'm trying to bind the IsChecked property of a CheckBox to a value on that subclass and no matter when I try I can't seem to get it to work. Hopefully I'm just missing something simple.

In my main program I have the following, and it works fine for detecting changes to "SomeProperty" on the "MyDevice" class:

ObservableCollection<MyDevice> MyDevices = new ObservableCollection<MyDevice>();
DevicesGrid.ItemSource = MyDevices;

My class definition is below:

public class MyDevice : INotifyPropertyChanged
{
    public class Input : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void RaisePropertyChanged([CallerMemberName] string PropertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
        }

        private bool _SyncDetected;
        public bool SyncDetected
        {
            get { return _SyncDetected; }
            set { _SyncDetected = value; RaisePropertyChanged(); }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void RaisePropertyChanged([CallerMemberName] string PropertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }

    private bool _SomeProperty;
    public bool SomeProperty
    {
        get { return _SomeProperty; }
        set { _SomeProperty = value; RaisePropertyChanged(); }
    }

    public ObservableCollection<Input> MyInputs = new ObservableCollection<Input>() { new Input(), new Input() };
}

And this is my XAML:

<DataGrid x:Name="DevicesGrid" Margin="10,80,10,10" AutoGenerateColumns="False">
    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource {x:Type DataGridRow}}">
            <Setter Property="ContextMenu" Value="{StaticResource DeviceRowContextMenu}"/>
        </Style>
    </DataGrid.RowStyle>
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Sync/Hotplug" IsReadOnly="True" Width="Auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Margin="2,2,2,2" VerticalAlignment="Center" HorizontalAlignment="Center">
                        <CheckBox Margin="2,2,2,2" IsHitTestVisible="False" IsChecked="{Binding MyInputs[0].SyncDetected}" Content="In1"/>
                        <CheckBox Margin="2,2,2,2" IsHitTestVisible="False" IsChecked="{Binding MyInputs[1].SyncDetected}" Content="In2"/>
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>        
    </DataGrid.Columns>
</DataGrid>

I'm really new at working with WPF so any help is appreciated. Thanks.

1
If there are only two CheckBox, why do you need an observablecollection? - Ayyappan Subramanian
or alternatively, if you're using an observablecollection you should instead be using an ItemsCollection to display the check boxes - Tim Rutter
why don't you bind to MyDevices: <DataGrid x:Name="DevicesGrid" ItemsSource="{Binding MyDevices}" Margin="10,80,10,10" AutoGenerateColumns="False"> - Tim Rutter
What exactly is it that isn't working? I can't see anything immediately wrong (other than its not really the right way to do things) with the above - Tim Rutter
@TimRutter It doesn't show the correct data as it never seems to update. What's the difference between ItemsSource="{Binding MyDevices}" and DevicesGrid.ItemSource = MyDevices; in C# code? I'll research ItemsCollection, but in the meantime can you offer more advice about what I'm doing 'not really the right way'? - Chris

1 Answers

1
votes

Here is something wrong:

public ObservableCollection<Input> MyInputs = new ObservableCollection<Input>() { new Input(), new Input() };

MyDevice.MyInputs is a field, not a property, so the binding system cannot find it through reflection.