In the below UserControl for a DataGrid, the line:
<customcontrols:AppointmentListView ItemsSource="{Binding columns[0].appointmentKeys}" Height="140" Background="Bisque">
performs a binding to a column by its index, how is this binding made in Elmish.WPF?
Assuming the DataContext for this line is Rows, in C# the Row is defined as:
public class Row : IRow
{
public string rowTime { get; set; }
public List<ICell> columns { get; set; }
private const int columnCount = 4;
public Row(int rowNumber, string rowTime)
{
this.rowTime = rowTime;
this.columns = new List<ICell>();
for (int i = 0; i < columnCount; i++)
{
var t = TimeSpan.FromMinutes(i * 15);
columns.Add(new Cell(rowNumber, i, t));
}
}
public Row()
{
}
// Indexer declaration. If index is out of range, the rows array will throw the exception.
public ICell this[int index]
{
get { return columns[index]; }
set { columns[index] = value; }
}
}
Thanks in Advance!
In full disclosure, here is the full UserControl XAML:
<!--
Assign the ROOT element of a user control a name. Usual name is LayoutRoot or Root. This will be used as reference with
ElementName. Do not set the DataContext of a usercontrol
-->
<UserControl.Resources>
<local:IsNullConverter x:Key="isNullConverter"/>
<!-- DataContext is AppointmentKey -->
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding tservice, Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="Background" Value="LawnGreen" />
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Border BorderBrush="Black" BorderThickness="4" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!--The DataContext for this user control is the AppointmentEditor.
A customcontrol for the DataGrid is being used to listen for events from the selected item. Selecting an item raises an
custom routed event from the customcontrols:AppointmentListView. The Cells of the datagrid consists of AppointmentListViews -->
<TextBlock Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="4" Text="{Binding SelectedAppointmentDate, StringFormat=D}"
FontSize="24" FontWeight="ExtraBold" TextAlignment="Center"/>
<TextBlock Grid.Row="0" Grid.Column="6" x:Name="CurrentTime" Width="60"
HorizontalAlignment="Right" Margin="2" FontWeight="SemiBold" FontSize="14"/>
<!--
A customcontrol for the DataGrid is being used to listen for events from the selected item. Selecting an item raises a
custom routed event from the customcontrols:AppointmentListView. The Cells of the datagrid consists of AppointmentListView.
customcontrols:AppointmentListView.ScheduledAppointment is defined as a routed event. This syntax attaches the routed event
to the AppointmentDataGrid_ScheduledAppointment handler found in the code-behind. The AppointmentListView is being attached
to each Cell of the AppointmentDataGrid.
-->
<customcontrols:AppointmentDataGrid x:Name="AppointmentTable" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="4" Grid.RowSpan="6"
ItemsSource="{Binding Rows}" AutoGenerateColumns="False"
CanUserAddRows="False" AlternationCount="2" AlternatingRowBackground="LightYellow"
customcontrols:AppointmentListView.ScheduledAppointment ="AppointmentDataGrid_ScheduledAppointment"
SelectedItem="{Binding SelectedRow}"
>
<DataGrid.Columns>
<!--The DataContext for DataGrid Columns is from the itemsSource Rows.
The Syntax is to address the content objects within a cell is Row[columindex] or Row["column header"] -->
<DataGridTextColumn Header="Time" Binding="{Binding RowTime}" />
<DataGridTemplateColumn Header="0:00" Width="354" IsReadOnly="True">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!--A custom control is required here to detect mouse events and raise a routed event. A Behavior cannot raise a routed event.-->
<!--The DataContext here is from the ItemsSource Row-->
<customcontrols:AppointmentListView ItemsSource="{Binding columns[0].appointmentKeys}" Height="140" Background="Bisque">
<ListView.View>
<GridView>
<GridViewColumn Header="First" DisplayMemberBinding="{Binding firstName}" Width="100"/>
<GridViewColumn Header="Last" DisplayMemberBinding="{Binding lastName}" Width="120"/>
<GridViewColumn Header="BirthDate" DisplayMemberBinding="{Binding birthDate, StringFormat=d}" Width="100"/>
</GridView>
</ListView.View>
</customcontrols:AppointmentListView>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="0:15" Width="354" IsReadOnly="True">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<customcontrols:AppointmentListView ItemsSource="{Binding columns[1].appointmentKeys}" Height="140" Background="Bisque">
<ListView.View>
<GridView>
<GridViewColumn Header="First" DisplayMemberBinding="{Binding firstName}" Width="100"/>
<GridViewColumn Header="Last" DisplayMemberBinding="{Binding lastName}" Width="120"/>
<GridViewColumn Header="BirthDate" DisplayMemberBinding="{Binding birthDate, StringFormat=d}" Width="100"/>
</GridView>
</ListView.View>
</customcontrols:AppointmentListView>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="0:30" Width="354" IsReadOnly="True" >
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<customcontrols:AppointmentListView ItemsSource="{Binding columns[2].appointmentKeys}" Height="140" Background="Bisque">
<ListView.View>
<GridView>
<GridViewColumn Header="First" DisplayMemberBinding="{Binding firstName}" Width="100"/>
<GridViewColumn Header="Last" DisplayMemberBinding="{Binding lastName}" Width="120"/>
<GridViewColumn Header="BirthDate" DisplayMemberBinding="{Binding birthDate, StringFormat=d}" Width="100"/>
</GridView>
</ListView.View>
</customcontrols:AppointmentListView>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="0:45" Width="354" IsReadOnly="True">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<customcontrols:AppointmentListView ItemsSource="{Binding columns[3].appointmentKeys}" Height="140" Background="Bisque">
<ListView.View>
<GridView>
<GridViewColumn Header="First" DisplayMemberBinding="{Binding firstName}" Width="100"/>
<GridViewColumn Header="Last" DisplayMemberBinding="{Binding lastName}" Width="120"/>
<GridViewColumn Header="BirthDate" DisplayMemberBinding="{Binding birthDate, StringFormat=d}" Width="100"/>
</GridView>
</ListView.View>
</customcontrols:AppointmentListView>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</customcontrols:AppointmentDataGrid>
</Grid>
</Border>
</UserControl>
As it turns out, when the supporting Module in F# is correct, Elmish.WPF will correctly use the index [] notation as demonstrated in: https://github.com/awaynemd/MyDataGrid
The working parts are: