• 自定义控件为了虚拟化表结构


    I’ve just Copied the Article of paul van bladel for sharing, original link:

    http://blog.pragmaswitch.com/?p=318

     

    Introduction

    LightSwitch has a powerful and robust set of standard controls which are doing a great job. Apart from that there is always the possibility the create your own custom controls.

    That’s what we will do in this post.

    I want to demonstrate a way to visualize data of rooms and their corresponding reservations on a kind of “plan board”. This differs radically from a normal datagrid because the visualization that we have in mind has kind of undefined amount of “columns.

    The Data model

    We have a pretty simple Parent-child relationship between rooms and reservations.

    For completeness, here the Reservation entity design:

    As you can see a reservation has a slot property, which is the reservation date. A room can only reserved for at least a full day. Apart from the link to the room in question, a reservation has as well a state property. In my simple example this can be A, B or C, but you can use your imagination to think about something more realistic.

    The classic list-detail representation

    How do we want to visualize the room reservations?

    I will not focus here on a graphical masterpiece, I limit things to a spartan representation in such a way all attention can go to the necessary plumbing.

    You can click on a current reservation and a modal form will pop up:

    The necessary ingredients

    The Xaml

    <UserControl xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"  x:Class="LightSwitchApplication.ReservationSilverlightControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                     xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
        mc:Ignorable="d" xmlns:local="clr-namespace:LightSwitchApplication"
        d:DesignHeight="300" d:DesignWidth="400">
        <UserControl.Resources>
            <local:PeriodParameters x:Key="PeriodParameters"></local:PeriodParameters>
            <local:ReservationValueConverter x:Key="ReservationValueConverter"></local:ReservationValueConverter>
        </UserControl.Resources>
        <Grid x:Name="LayoutRoot" Background="White"  DataContext="{Binding Screen}"  Loaded="LayoutRoot_Loaded" >
            <sdk:DataGrid  AutoGenerateColumns="False" x:Name="grid"  ItemsSource="{Binding Rooms}">
                <sdk:DataGrid.Columns>
                    <sdk:DataGridTextColumn
                                 Binding="{Binding Name}"
                                 Header="Name"/>
                    <sdk:DataGridTemplateColumn   Width="*">
                        <sdk:DataGridTemplateColumn.HeaderStyle>
                            <Style
                              TargetType="primitives:DataGridColumnHeader">
                                <Setter
                                  Property="HorizontalContentAlignment"
                                  Value="Stretch" />
                                <Setter
                                  Property="VerticalContentAlignment"
                                  Value="Stretch" />
                                <Setter Property="Margin"
                                             Value="0" />
                                <Setter Property="ContentTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <ItemsControl
                              ItemsSource="{Binding Source={StaticResource PeriodParameters},Path=DateList,Mode=TwoWay}">
                                                <ItemsControl.ItemsPanel>
                                                    <ItemsPanelTemplate>
                                                        <StackPanel
                                             Orientation="Horizontal">
                                                        </StackPanel>
                                                    </ItemsPanelTemplate>
                                                </ItemsControl.ItemsPanel>
                                                <ItemsControl.ItemTemplate>
                                                    <DataTemplate>
                                                        <Border  Width="25" >
                                                            <TextBlock Text="{Binding }"
                                                  TextAlignment="Center"/>
                                                        </Border>
                                                    </DataTemplate>
                                                </ItemsControl.ItemTemplate>
                                            </ItemsControl>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </sdk:DataGridTemplateColumn.HeaderStyle>
                        <sdk:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ItemsControl ItemsSource="{Binding Converter={StaticResource ReservationValueConverter},  ConverterParameter={StaticResource PeriodParameters}}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate  >
                                            <StackPanel   Orientation="Horizontal"/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <StackPanel>
                                                <Border Width="25">
                                                    <TextBlock Height="25" Width="25" TextAlignment="Center"
                                                               MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"
                                                               Tag="{Binding Id}"  Text="{Binding State}">
                                                    </TextBlock>
                                                </Border>
                                            </StackPanel>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </DataTemplate>
                        </sdk:DataGridTemplateColumn.CellTemplate>
                    </sdk:DataGridTemplateColumn>
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>
        </Grid>
    </UserControl>

    You’ll notice that my control is basically a datagrid with 2 columns where the first column (a DataGridTextColumn)  is bound to the room visual collection and the second column ( a DataGridTemplateColumn) is in fact a stackpanel which “horizontalises” the reservations for the current room.

    One difficulty is here that a room does not necessary have reservations for the complete time frame for which the overview is requested. Also finding out the right way to do the binding was, at least for me, a challenge.

    The Xaml Code behind

    public partial class ReservationSilverlightControl : UserControl
        {
            public ReservationSilverlightControl()
            {
                InitializeComponent();
                PeriodParameters.DateList = new ObservableCollection<string>();
            }
     
            private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                TextBlock textBlock = sender as TextBlock;
                var context = (IContentItem)this.DataContext;
                var screen = (IScreenObject)context.Screen;
     
                if (textBlock.Tag != null)
                {
                    int myReservation = int.Parse(textBlock.Tag.ToString());
     
                    screen.Details.Dispatcher.BeginInvoke(() =>
                        {
     
                            screen.Details.Properties["CurrentReservationId"].Value = myReservation;
                            screen.Details.Methods["EditDetails"].CreateInvocation(null).Execute();
                        });
                }
                else
                {
                    //here we could  call a create reservation screen.
                }
     
            }
     
            private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
            {
                if (((sender as Grid).DataContext as SimpleCustomControl).StartDate.HasValue)
                {
                    PeriodParameters.StartDate = ((sender as Grid).DataContext as SimpleCustomControl).StartDate.Value.Date;
                }
                else
                {
                    PeriodParameters.StartDate = DateTime.Now.Date;
                }
     
                if (((sender as Grid).DataContext as SimpleCustomControl).EndDate.HasValue)
                {
                    PeriodParameters.EndDate = ((sender as Grid).DataContext as SimpleCustomControl).EndDate.Value.Date;
                }
                else
                {
                    PeriodParameters.EndDate = DateTime.Now.AddDays(31).Date;
                }
     
                TimeSpan span = PeriodParameters.EndDate - PeriodParameters.StartDate;
     
                for (int i = 0; i <= span.Days; i++)
                {
                    PeriodParameters.DateList.Add(PeriodParameters.StartDate.AddDays(i).Day.ToString());
                }
            }
        }

    The row ValueConverter

    public class PeriodParameters
        {
            public PeriodParameters() { }
            public static ObservableCollection<string> DateList { get; set; }
            public static DateTime StartDate { get; set; }
            public static DateTime EndDate { get; set; }
        }
     
        public class ReservationValueConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                ObservableCollection<Reservation> reservationObservableCollection = new ObservableCollection<Reservation>();
                Room currentRoom = value as Room;
                var query = currentRoom.ReservationsQuery as IExecutableWithResult;
                query.ExecuteCompleted += new EventHandler<ExecuteCompletedEventArgs>((s, e) =>
                {
                    IEnumerable<Reservation> reservationList = query.Result as IEnumerable<Reservation>;
     
                    DateTime startDate = PeriodParameters.StartDate.Date;
                    DateTime endDate = PeriodParameters.EndDate.Date;
                    TimeSpan span = endDate - startDate;
                    for (int i = 0; i <= span.Days; i++)
                    {
                        Reservation reservation = reservationList.Where(r => r.Slot.Date == startDate.AddDays(i)).SingleOrDefault();
     
                        reservationObservableCollection.Add(reservation);
                    }
                });
                query.ExecuteAsync();
                return reservationObservableCollection;
            }
     
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return value;
            }
        }

    As you can see, the row IValueConverter will load for each room row the corresonding reservation data in an asynchronous way. So, if you have a lot of reservation data, the loading can take a few seconds, but it will never block the screen.

    The LightSwitch screen.

    The LightSwitch screen containing the reservation control is very light and contains only the code for showing the modal form for editing the current reservation:

    public partial class SimpleCustomControl
       {
           partial void EditDetails_Execute()
           {
               this.OpenModalWindow("CurrentReservation");
           }
       }

    Sample Project

    You can find here  the sample project: RoomReservation. It contains also functionality to generate some working test data.

    Enjoy !

    Many thanks to Lifeng for the help on the LightSwitch forum.

  • 相关阅读:
    Qt/Qml 电子书阅读器
    Qt/Qml 翻页特效
    vue如何引入本地js(不被打包编译的js)文件
    CSS3解决移动端手指点击或滑动屏幕时出现的浅蓝色背景框
    vue移动端touch插件
    vue组件间通信六种方式(完整版)
    Vue 过渡实现轮播图
    vue中遇到的坑 --- 变化检测问题(数组相关)
    Vue判断设备是移动端还是pc端
    vue项目如何监听窗口变化,达到页面自适应?
  • 原文地址:https://www.cnblogs.com/otomii/p/2530949.html
Copyright © 2020-2023  润新知