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 boxesTim 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 aboveTim 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.