Hi guys!
I need to create a Schedule Week View for my application, I've tried many different options and still in a dead end, you could see questions within a week.
Slider just increase RowHeight property.
Video : https://cloud.mail.ru/public/MNUP/ydAmWVXhu
I originally made columns using ListView, then rebuilt all using StackLayout or RepeaterView, now I'm using the Grid.
My problem is: I need to do a grid zoom (increase row height and column width), but with all the above layouts, there are performance issues.
When I used StackLayout, I increased the height of each element through the bindable property. Now that I'm using the Grid, I increase the Height property of each row through the bindable property. But when I do this it's very slow and freeze.
My Realization classes:
- ScheduleWeekView.xaml
- DayInfo.xaml show Day of week and Day of the month
- JobObjectTemplate.xaml this is cell of the grid
My logic: in the code file, I create the lines and associate them with RowHeightProperty, when I get List WeekItems I start filling out the table with elements. If there are more elements, I add lines.
DayInfo contains the day of the month and all Jobs for that day
ScheduleWeekView.xaml
<ContentView.Content>
<ScrollView
x:Name="ScrollView"
BindingContext="{x:Reference This}"
Orientation="Vertical">
<Grid
x:Name="ScheduleGrid"
ColumnSpacing="1"
RowSpacing="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- DayInfo -->
<week:DayInfoView
Grid.Column="0"
DayOfMonth="{Binding WeekItems[0].DayOfMonth}"
DayOfWeek="Mon" />
<week:DayInfoView
Grid.Column="1"
DayOfMonth="{Binding WeekItems[1].DayOfMonth}"
DayOfWeek="Tue" />
<week:DayInfoView
Grid.Column="2"
DayOfMonth="{Binding WeekItems[2].DayOfMonth}"
DayOfWeek="Wed" />
<week:DayInfoView
Grid.Column="3"
DayOfMonth="{Binding WeekItems[3].DayOfMonth}"
DayOfWeek="Thu" />
<week:DayInfoView
Grid.Column="4"
DayOfMonth="{Binding WeekItems[4].DayOfMonth}"
DayOfWeek="Fri" />
<week:DayInfoView
Grid.Column="5"
DayOfMonth="{Binding WeekItems[5].DayOfMonth}"
DayOfWeek="Sun" />
<week:DayInfoView
Grid.Column="6"
DayOfMonth="{Binding WeekItems[6].DayOfMonth}"
DayOfWeek="Mon" />
<Grid.GestureRecognizers>
<PinchGestureRecognizer PinchUpdated="PinchToZoomContainer_OnPinchUpdated" />
</Grid.GestureRecognizers>
</Grid>
</ScrollView>
</ContentView.Content>
ScheduleWeekView.xaml.cs
public partial class ScheduleWeekView : ContentView
{
#region Consts
private const double InitializeItemHeight = 50.0;
private const int DefaultRowCount = 10;
#endregion
#region BindableProperties
private static readonly BindableProperty ColumnWidthProperty =
BindableProperty.Create(
"ColumnWidth",
typeof(GridLength),
typeof(ScheduleWeekView),
new GridLength(),
BindingMode.TwoWay);
private static readonly BindableProperty RowHeightProperty =
BindableProperty.Create(
"RowHeight",
typeof(double),
typeof(ScheduleWeekView),
InitializeItemHeight,
BindingMode.TwoWay);
public static readonly BindableProperty WeekItemsProperty = BindableProperty.Create(
"WeekItems",
typeof(List<DayInfo>),
typeof(ScheduleWeekView),
propertyChanged: (bindable, value, newValue) =>
{
var days = (List<DayInfo>) newValue;
((ScheduleWeekView)bindable).FillGrid(days);
});
public static readonly BindableProperty ItemTappedCommandProperty = BindableProperty.Create(
"ItemTappedCommand",
typeof(ICommand),
typeof(ScheduleWeekView));
#endregion
#region Public Fields
public GridLength ColumnWidth
{
get => (GridLength) GetValue(ColumnWidthProperty);
set => SetValue(ColumnWidthProperty, value);
}
public double RowHeight
{
get => (double)GetValue(RowHeightProperty);
set => SetValue(RowHeightProperty, value);
}
public ICommand ItemTappedCommand
{
get => (ICommand)GetValue(ItemTappedCommandProperty);
set => SetValue(ItemTappedCommandProperty, value);
}
public List<DayInfo> WeekItems
{
get => (List<DayInfo>) GetValue(WeekItemsProperty);
set => SetValue(WeekItemsProperty, value);
}
#endregion
#region Private Fields
private int _rowCount;
#endregion
#region Init
public ScheduleWeekView()
{
InitializeComponent();
InitializeGrid();
}
private void InitializeGrid()
{
AddRows(DefaultRowCount);
}
#endregion
#region Events
private void PinchToZoomContainer_OnPinchUpdated(object sender,
PinchGestureUpdatedEventArgs e)
{
/*if (e.Status == GestureStatus.Started)
{
_startScale = ItemHeight;
}
if (e.Status == GestureStatus.Running)
{
_currentScale = e.Scale * _startScale;
ItemHeight = Math.Max(InitializeItemHeight, _startScale);
}*/
}
#endregion
#region Private Methods
private void FillGrid(List<DayInfo> days)
{
if (ReferenceEquals(days, null))
return;
for (int i = 0; i <= 6; i++)
{
FillColumn(days[i], i);
}
}
private void FillColumn(DayInfo day, int column)
{
if (ReferenceEquals(day.Items, null))
return;
var itemsCount = day.Items.Count;
var rowToAdd = _rowCount - itemsCount;
if (rowToAdd < 0)
AddRows(rowToAdd);
for (int i = 0; i < itemsCount; i++)
{
var template = CreateJobView(day.Items[i]);
PasteItem(template, column, i + 1);
}
}
private JobObjectTemplate CreateJobView(JobObject jo)
{
var template = new JobObjectTemplate
{
BindingContext = jo,
};
Binding itemTappedCommandBinding =
new Binding("ItemTappedCommand", source: this);
template.SetBinding(JobObjectTemplate.ItemTappedCommandProperty,
itemTappedCommandBinding);
return template;
}
private void PasteItem(View view, int column, int row)
{
ScheduleGrid.Children.Add(view, column, row);
}
private void AddRows(int count)
{
for (int i = 0; i < count; i++)
{
var row = CreateRowDefenition();
ScheduleGrid.RowDefinitions.Add(row);
}
_rowCount += count;
}
private RowDefinition CreateRowDefenition()
{
var row = new RowDefinition();
Binding heightBinding = new Binding("RowHeight", source: this);
row.SetBinding(RowDefinition.HeightProperty, heightBinding);
return row;
}
#endregion
}