如何在Xamarin.forms中创建自定义数据网格

时间:2017-01-27 13:04:21

标签: c# xaml datagrid xamarin.forms

目前我正在创建用于将数据列表显示为Grid的自定义数据网格。我从Github获得了一些示例源。基于示例源,我已根据我的要求进行了修改。但是在访问listview数据时我遇到了一些问题 1.当我点击那个特定的单元格时,我能够改变特定的单元格背景颜色。但是需要获得相关的行进行一些计算。

  1. 我需要区分标记的细胞和未标记的细胞。一旦我点击了单元格。

  2. 我的问题是如何在同一时间点击单元格区分单元格以进行计算Output Screen shot

  3. Code Snap:

    public class DataGrid : StackLayout
        {
    
            #region binding properties
    
          //  public static BindableProperty ItemClickCommandProperty = BindableProperty.Create<DataGrid, ICommand>(x => x.ItemClickCommand, null);
    
    
            public static readonly BindableProperty HeaderBackgroundProperty =
                                 BindableProperty.Create<DataGrid, Color>((p) => p.HeaderBackground, Color.Aqua);
    
            public static readonly BindableProperty HeaderTextColorProperty =
                                BindableProperty.Create<DataGrid, Color>((p) => p.HeaderTextColor, Color.Black);
    
            public static readonly BindableProperty EvenRowBackgroundProperty =
                                BindableProperty.Create<DataGrid, Color>((p) => p.EvenRowBackground, Color.White);
    
            public static readonly BindableProperty OddRowBackgroundProperty =
                                 BindableProperty.Create<DataGrid, Color>((p) => p.OddRowBackground, Color.White);
    
            public static readonly BindableProperty EvenRowForegroundProperty =
                                BindableProperty.Create<DataGrid, Color>((p) => p.EvenRowForeground, Color.Black);
    
            public static readonly BindableProperty OddRowForegroundProperty =
                                BindableProperty.Create<DataGrid, Color>((p) => p.OddRowForeground, Color.Black);
    
            public static readonly BindableProperty ColumnsProperty =
                                BindableProperty.Create<DataGrid, ColumnCollection>((p) => p.Columns, null, BindingMode.TwoWay, null, UpdateColumns);
    
            public static readonly BindableProperty ItemsSourceProperty =
                                BindableProperty.Create<DataGrid, IEnumerable>((p) => p.ItemsSource, null, BindingMode.TwoWay, null, DrawDataGrid);
    
            public static readonly BindableProperty RowHeightProperty =
                                BindableProperty.Create<DataGrid, double>((p) => p.RowHeight, 40);
    
            public static readonly BindableProperty HeaderHeightProperty =
                                BindableProperty.Create<DataGrid, double>((p) => p.HeaderHeight, 40);
    
            public static readonly BindableProperty IsSortableProperty =
                                BindableProperty.Create<DataGrid, bool>((p) => p.IsSortable, true);
    
            public static readonly BindableProperty HeaderFontSizeProperty =
                                BindableProperty.Create<DataGrid, double>((p)=>p.HeaderFontSize,13);
    
            private static void DrawDataGrid(BindableObject bindable, IEnumerable oldValue, IEnumerable newValue)
            {
                if ((bindable as DataGrid).Columns.Count > 0 && !(bindable as DataGrid).hasInitialized)
                    (bindable as DataGrid).InitilizeUI();
            }
    
            private static void UpdateColumns(BindableObject bindable, ColumnCollection oldValue, ColumnCollection newValue)
            {
                if (!(bindable as DataGrid).hasInitialized && newValue.Count > 0)
                    (bindable as DataGrid).InitilizeUI();
            }
    
            #endregion
    
            #region properties
            public Color HeaderBackground
            {
                get { return (Color)GetValue(HeaderBackgroundProperty); }
                set { SetValue(HeaderBackgroundProperty, value); }
            }
    
            public Color HeaderTextColor
            {
                get { return (Color)GetValue(HeaderTextColorProperty); }
                set { SetValue(HeaderTextColorProperty, value); }
            }
    
            public Color EvenRowBackground
            {
                get { return (Color)GetValue(EvenRowBackgroundProperty); }
                set { SetValue(EvenRowBackgroundProperty, value); }
            }
    
            public Color OddRowBackground
            {
                get { return (Color)GetValue(OddRowBackgroundProperty); }
                set { SetValue(OddRowBackgroundProperty, value); }
            }
    
            public Color EvenRowForeground
            {
                get { return (Color)GetValue(EvenRowForegroundProperty); }
                set { SetValue(EvenRowForegroundProperty, value); }
            }
    
            public Color OddRowForeground
            {
                get { return (Color)GetValue(OddRowForegroundProperty); }
                set { SetValue(OddRowForegroundProperty, value); }
            }
    
            public IList ItemsSource
            {
                get { return (IList)GetValue(ItemsSourceProperty); }
                set { SetValue(ItemsSourceProperty, value); }
            }
    
            public ColumnCollection Columns
            {
                get { return (ColumnCollection)GetValue(ColumnsProperty); }
                set { SetValue(ColumnsProperty, value); }
            }
    
            public double HeaderFontSize
            {
                get { return (double)GetValue(HeaderFontSizeProperty); }
                set { SetValue(HeaderFontSizeProperty,value); }
            }
    
            public double RowHeight
            {
                get { return (double)GetValue(RowHeightProperty); }
                set { SetValue(RowHeightProperty, value); }
            }
    
            public double HeaderHeight
            {
                get { return (double)GetValue(HeaderHeightProperty); }
                set { SetValue(HeaderHeightProperty, value); }
            }
            public bool IsSortable
            {
                get { return (bool)GetValue(IsSortableProperty); }
                set { SetValue(IsSortableProperty, value); }
            }
    
            #endregion
    
            #region fields
    
            bool hasInitialized = false;
            Dictionary<int, SortingOrder> SortingOrders;
            ListView listView;
            #endregion
    
            #region ctor
            public DataGrid()
            {
                SortingOrders = new Dictionary<int, SortingOrder>();
    
                this.Columns = new ColumnCollection();
                this.Padding = 5;
                this.Spacing = 0;
                this.BackgroundColor = Color.White;
                this.VerticalOptions = LayoutOptions.Fill;
    
    
                listView = new ListView()
                {
                    SeparatorVisibility = SeparatorVisibility.None,
    
                    ItemTemplate = new DataTemplate(GetRowTemplate),
                 };
    
                //  listView.ItemTapped += this.OnItemTapped;
                listView.ItemTapped +=  (sender, e) =>
                 {
                     if (e.Item != null)
                     {
                         var selectedItem = e.Item;
                     }
    
                    // await  Xamarin.Forms.Page.DisplayAlert();
                 };
    
    
                listView.ItemSelected += (s, e) =>
                {
                    listView.SelectedItem = null;
                };
            }
            #endregion
    
            //public ICommand ItemClickCommand
            //{
            //    get { return (ICommand)this.GetValue(ItemClickCommandProperty); }
            //    set { this.SetValue(ItemClickCommandProperty, value); }
            //}
    
            //private void OnItemTapped(object sender, ItemTappedEventArgs e)
            //{
            //    if (e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e))
            //    {
            //        this.ItemClickCommand.Execute(e.Item);
            //        listView.SelectedItem = null;
            //    }
            //}
    
    
            public void InitilizeUI()
            {
                hasInitialized = true;
    
                if (IsSortable)
                {
                    for (int i = 0; i < Columns.Count; i++ )
                        SortingOrders.Add(i, SortingOrder.NotDetermined);
                }
    
                listView.ItemsSource = ItemsSource;
                listView.RowHeight = (int)RowHeight;
                this.Children.Add(GetHeader());
    
                if (Device.OS == TargetPlatform.Android)
                {
                    ScrollView sv = new ScrollView();
                    sv.Content = listView;
                    this.Children.Add(sv);
                }
                else
                    this.Children.Add(listView);
    
            }
    
            protected virtual Grid GetHeader()
            {
                Grid header = new Grid()
                {
                    HeightRequest = HeaderHeight,
                    Padding = new Thickness(1),
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    RowSpacing = 0,
                    ColumnSpacing = 1,
                    BackgroundColor = Color.Black,
                };
    
                header.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(HeaderHeight, GridUnitType.Absolute) });
    
                foreach (var col in Columns)
                {
                    header.ColumnDefinitions.Add(new ColumnDefinition() { Width = col.Width });
                }
    
                for (int i = 0; i < Columns.Count; i++)
                {
                    Label lb = new Label()
                    {
                        Text = Columns[i].Title,
                        VerticalOptions = LayoutOptions.CenterAndExpand,
                        HorizontalOptions = LayoutOptions.CenterAndExpand,
                        TextColor = HeaderTextColor,
                        FontAttributes = Xamarin.Forms.FontAttributes.Bold,
                        XAlign = TextAlignment.Center,
                        YAlign = TextAlignment.Center,
                        LineBreakMode = Xamarin.Forms.LineBreakMode.WordWrap,
                        FontSize=HeaderFontSize,
                    };
    
                    StackLayout sl = new StackLayout()
                    {
                        BackgroundColor = HeaderBackground,
                        VerticalOptions = LayoutOptions.FillAndExpand,
                        Orientation = StackOrientation.Horizontal,
                        Children = { lb }
                    };
    
                    if (IsSortable)
                    {
                        var orderingIcon = new Label()
                        {
                            VerticalOptions = LayoutOptions.Center,
                            Text = " ",
                        };
    
                        Columns[i].Params = orderingIcon;
                        sl.Children.Add(orderingIcon);
    
                        string property = Columns[i].DataProperty;
                        string title = Columns[i].Title;
                        var tgr = new TapGestureRecognizer();
                        tgr.Tapped += (s, e) => {
                            var col = Columns.FirstOrDefault(x=> x.DataProperty == property && x.Title == title);
                            SortItems(Columns.IndexOf(col)); 
                        };
                        sl.GestureRecognizers.Add(tgr);
                    }
                    header.Children.Add(sl);
    
                    Grid.SetColumn(sl, i);
                }
                return header;
            }
    
            bool isEven = false;
            bool first = true;
            object GetRowTemplate()
            {
                KowalskiViewCell row = new KowalskiViewCell();
                Grid rowGrid = new Grid()
                {
                    BackgroundColor = Color.Black,
                    RowSpacing = 0,
                    ColumnSpacing = 1,
                    Padding = new Thickness(1, first ? 1 : 0, 1, 1)
                };
    
                first = false;
                for (int i = 0; i < this.Columns.Count; i++)
                    rowGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = Columns[i].Width });
                int i1 = 0;
                for (int i = 0; i < this.Columns.Count; i++)
                {
                    i1++;
                    ContentView cell = new ContentView()
                    {
                        HorizontalOptions = LayoutOptions.Fill,
                        VerticalOptions = LayoutOptions.Fill,
                        BackgroundColor = (isEven) ? EvenRowBackground : OddRowBackground
                    };
    
                    if(Columns[i].CellTemplate!= null)
                    {
                        View v = Columns[i].CellTemplate.CreateContent() as View;
                        v.HorizontalOptions = Columns[i].HorizontalContentAlignment;
                        cell.Content = v;
                    }
    
                    else if (Columns[i].DataProperty != null)
                    {
                        Label text = new Label()
                        {
                            VerticalOptions = LayoutOptions.Center,
                            HorizontalOptions = Columns[i].HorizontalContentAlignment,
                            TextColor = (isEven) ? OddRowForeground : EvenRowForeground,
                            FontSize = 12,
                        };
    
                        //Here implemeting Logic 
    
                        if (Columns[i].DataProperty == "Name" || Columns[i].DataProperty == "Goal" || Columns[i].DataProperty == "Achieved" || Columns[i].DataProperty == "Net")
                            text.SetBinding(Label.TextProperty, new Binding(Columns[i].DataProperty, BindingMode.TwoWay));
    
                        var tgr = new TapGestureRecognizer();
    
                        var property = Columns[i].DataProperty;
    
    
                    var textval  =  text.GetValue(Label.TextProperty);
    
                        tgr.Tapped += (s, e) =>
                        {
                            if (property != "Name" && property != "Goal" && property != "Achieved" && property != "Net")
                            {
                                cell.BackgroundColor = Color.Green;
                                text.FontSize = 24;
                                text.TextColor = Color.White;
    
                                text.Text = i1.ToString();
                            }
                        };
                        cell.GestureRecognizers.Add(tgr);
    
                        cell.Content = text;
                    }
    
                    rowGrid.Children.Add(cell);
                    Grid.SetColumn(cell, i);
                }
    
                isEven = !isEven;
                row.View = rowGrid;
                return row;
            }
    
            private void SortItems(int propertyIndex)
            {
                if (ItemsSource == null || ItemsSource.Count <= 1)
                    return;
    
                List<Object> item = new List<Object>();
                foreach (var itm in ItemsSource)
                    item.Add(itm);
    
                List<Object> sortedItems;
    
    
                if (!IsSortable)
                    throw new InvalidOperationException("This DataGrid is not sortable");
                if (Columns[propertyIndex].DataProperty == null)
    
                    throw new InvalidOperationException("Please set the DataProperty property of Column");
                if (SortingOrders[propertyIndex] != SortingOrder.Descendant)
                {
                    int i = 0;
                    var itm = item[0].GetType().GetRuntimeProperty(Columns[propertyIndex].DataProperty).GetValue(item[0]);
                    if (itm is decimal)
                        i++;
                    if (itm is double)
                        i++;
                    sortedItems = item.OrderByDescending((x) => x.GetType().GetRuntimeProperty(Columns[propertyIndex].DataProperty).GetValue(x)).ToList();
                    SortingOrders[propertyIndex] = SortingOrder.Descendant;
                    (Columns[propertyIndex].Params as Label).Text = "▼";
                }
                else
                {
                    sortedItems = item.OrderBy((x) => x.GetType().GetRuntimeProperty(Columns[propertyIndex].DataProperty).GetValue(x)).ToList();
                    SortingOrders[propertyIndex] = SortingOrder.Ascendant;
                    (Columns[propertyIndex].Params as Label).Text = "▲";
                }
    
                foreach (var column in Columns)
                {
                    if ((column.Params as Label).Text!= null && Columns[propertyIndex] != column )
                        (column.Params as Label).Text = " ";
                }
    
                isEven = false;
                listView.ItemsSource = sortedItems;
            }
        }
    

1 个答案:

答案 0 :(得分:1)

您尝试实施的功能已在原始存储库[here]中实现。

已提出拉取请求:here