0

So I think the title is a little confusing, but I couldn't think of anything better. Here's what I have:

CueSheet.cs

class CueSheet : INotifyPropertyChanged
{
   private ObservableCollection<Track> _tracks;
      public ObservableCollection<Track> Tracks
      {
         get => _tracks;
         set
         {
            if (_tracks != value)
               _tracks = value;
            NotifyPropertyChanged();
         }
      }

      private string _path;
      public string Path
      {
         get => _path;
         private set
         {
            if (_path != value)
               _path = value;
            NotifyPropertyChanged();
         }
      }

   ... other code...
}


public class Track : INotifyPropertyChanged
{
   ... INotifyPropertyChanged event handler ...

   private string _title;
   public string Title
   {
      get => _title;
      set
      {
         _title = value;
         NotifyPropertyChanged();
      }
   }

  ... 2 more properties (Frame and Index) coded as above ...
}

MainWindow.xaml.cs

public partial class MainWindow : INotifyPropertyChanged
{
   CueSheet cueSheet;

   public MainWindow()
   {
      InitializeComponent();

      cueSheet = new CueSheet();

      this.DataContext = this;

      // DataContext Bindings
      txtCueFilePath.DataContext = cueSheet;
      dgCueTracks.DataContext = cueSheet;
   }

   ...Other Code...
}

cueSheet is populated later in the code by reading from a file.

MainWindow.xaml

... other code ...

<TextBox Name="txtCueFilePath" 
         Grid.Row="1" Grid.Column="1"
         IsReadOnly="False" 
         Background="LightGray"
         Text="{Binding Path=Path, Mode=OneWay}"/>

... other code ...

<DataGrid Grid.Column="2" Name="dgCueTracks2"
                          BorderBrush="Black" BorderThickness="1"
                          Margin="0 5 5 5"
                          AutoGenerateColumns="False"
                          ItemsSource="{Binding Path=Tracks}">
   <DataGrid.Columns>
      <DataGridTextColumn Header="Title" Binding="{Binding Title}"/>
      <DataGridTextColumn Header="Index" Binding="{Binding Index}"/>
      <DataGridTextColumn Header="Frame" Binding="{Binding Frame}"/>
   </DataGrid.Columns>
</DataGrid>

... other code ...

Ok, so now that you see what I'm working with, I will say that this all works just fine. However I want to have all the binding taken care of in one place, and id like that place to be the XAML file. But I can't work out how to set the DataContext from inside the MainWindow.xaml. I see there is a Datacontext property for DataGrid and TextBox, but I can't figure out how to use them.

Clemens
  • 123,504
  • 12
  • 155
  • 268
master_ruko
  • 629
  • 1
  • 4
  • 22
  • A little search and you will find plenty of examples https://stackoverflow.com/questions/28941817/binding-windows-datacontext-to-the-window-itself-in-wpf – Cfun May 18 '20 at 19:10

2 Answers2

1

If you want any XAML element to refer to itself, you can use {RelativeSource}. To have the Window set itself as its own DataContext, just add the following to the opening tag of the Window:

DataContext="{Binding RelativeSource={RelativeSource Self}}"
Keith Stein
  • 6,235
  • 4
  • 17
  • 36
0

It appears that you cant bind a DataContext to a field, it has to be a property. Changing cueSheet to a property allowed me to bind it as the DataContext of my TextBox and DataGrid.

While

DataContext="{Binding cueSheet}"

didn't work because it was just a field, changing it to a property worked

DataContext="{Binding CueSheet}"

and I no longer need txtCueFilePath.DataContext = cueSheet; and dgCueTracks.DataContext = cueSheet; in the code-behind.

Clemens
  • 123,504
  • 12
  • 155
  • 268
master_ruko
  • 629
  • 1
  • 4
  • 22
  • The only thinks I changed was I made CueSheet into a property and added a DataContext binding for CueSheet to the DataGrid and TextBox controls – master_ruko May 18 '20 at 19:52