如何在Xamarin Forms中点击ViewCell后刷新TableView数据?

时间:2016-12-22 06:42:49

标签: c# .net xaml xamarin xamarin.forms

所以我有以下代码为我的TableView动态创建ViewCells:

XAML:

<StackLayout>
   <TableView Intent="Settings">
      <TableView.Root>
         <TableSection x:Name="tableSection"></TableSection>
      </TableView.Root>
   </TableView>
</StackLayout>

C#:

categories = getCategories();
foreach (var category in categories)
{
   var viewCell = new ViewCell 
   { 
      View = new StackLayout()
      {
         Padding = new Thickness(20, 0, 20, 0),
         HorizontalOptions = LayoutOptions.FillAndExpand,
         Children = { 
            new StackLayout() {
               Orientation = StackOrientation.Horizontal,
               VerticalOptions = LayoutOptions.CenterAndExpand,
               Children = {
                  new StackLayout() {
                     HorizontalOptions = LayoutOptions.StartAndExpand,
                     Children = {
                        new Label { Text = category.Name}
                      },
                  new StackLayout() {
                     HorizontalOptions = LayoutOptions.EndAndExpand,
                     Orientation = StackOrientation.Horizontal,
                     Children = {
                        new Label { Text = category.Count},
                        new Image { Source = "right1.png",
                                    IsVisible = category.Selected }
                     }
                  }
               }
            }
         }
       }
    };
    viewCell.Tapped += (sender, e) =>
    {
       if (category.Selected == false)
       {
          App.DB.UpdateSelected(true);
       }
       else
       {
          App.DB.UpdateSelected(false);
       }
       categories = getCategories();
       totalPhraseCount = getTotalPhraseCount();
       Title = totalPhraseCount.ToString() + " phrases";
     };
    tableSection.Add(viewCell);
}

我想要做的是每当我点击视图单元格来更新所选属性时,表格视图中的数据也会更新。在ListView中,我可以调用ItemSelected事件并使用更新的类别再次调用ItemSource。这可以用TableView吗?

3 个答案:

答案 0 :(得分:5)

试试这个:

enter image description here

<强> XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:App54"
             x:Class="App54.MainPage">

 <ContentPage.Content>
        <TableView Intent="Settings">
            <TableRoot>
                <TableSection x:Name="tableSection" Title="Section Title">
                </TableSection>
            </TableRoot>
        </TableView>
    </ContentPage.Content>
</ContentPage>

<强>的MainPage:

public partial class MainPage : ContentPage
{
    MyViewModel vm;

    public MainPage()
    {
        InitializeComponent();

        vm = new MyViewModel();

        foreach (MyDataModel dm in vm.Data)
        {
            Image img = new Image();
            img.SetBinding(Image.SourceProperty, "MyImage", BindingMode.TwoWay, null, null);
            img.BindingContext = dm;

            Label label1 = new Label();
            label1.SetBinding(Label.TextProperty, "MyLabel", BindingMode.TwoWay, null, null);
            label1.BindingContext = dm;

            Label label2 = new Label();
            label2.SetBinding(Label.TextProperty, "Selected", BindingMode.TwoWay, null, null);
            label2.BindingContext = dm;

            StackLayout sl = new StackLayout();
            sl.Orientation = StackOrientation.Horizontal;
            sl.Children.Add(img);
            sl.Children.Add(label1);
            sl.Children.Add(label2);

            ViewCell vc = new ViewCell();
            vc.BindingContext = dm;
            vc.View = sl;
            vc.Tapped += Vc_Tapped;

            tableSection.Add(vc);
        }
    }

    private void Vc_Tapped(object sender, EventArgs e)
    {
        ViewCell vc = (ViewCell)sender;
        MyDataModel dm = (MyDataModel)vc.BindingContext;

        MyDataModel currSel = vm.Data.FirstOrDefault(d => d.Selected == true);

        if (currSel != null)
            currSel.Selected = false;

        dm.Selected = true;
    }
}

<强>视图模型:

public class MyViewModel
{
    public ObservableCollection<MyDataModel> Data { get; set; }

    public MyViewModel()
    {
        Data = new ObservableCollection<MyDataModel>
        {
            new MyDataModel {MyLabel = "Label 1", MyImage = "image.png", Selected = false },
            new MyDataModel {MyLabel = "Label 2", MyImage = "image.png", Selected = false },
            new MyDataModel {MyLabel = "Label 3", MyImage = "image.png", Selected = false },
            new MyDataModel {MyLabel = "Label 4", MyImage = "image.png", Selected = false },
            new MyDataModel {MyLabel = "Label 5", MyImage = "image.png", Selected = false }
        };
    }
}

<强>型号:

public class MyDataModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    private string myLabel;
    public string MyLabel
    {
        get { return myLabel; }
        set
        {
            if (value != myLabel)
            {
                myLabel = value;
                PropertyChanged(this, new PropertyChangedEventArgs("MyLabel"));
            }
        }
    }
    private string myImage;
    public string MyImage
    {
        get { return myImage; }
        set
        {
            if (value != myImage)
            {
                myImage = value;
                PropertyChanged(this, new PropertyChangedEventArgs("MyImage"));
            }
        }
    }
    private bool selected;
    public bool Selected
    {
        get { return selected; }
        set
        {
            if (value != selected)
            {
                selected = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Selected"));
            }
        }
    }
}

答案 1 :(得分:2)

您应该使用绑定到viewmodel而不是手动设置值,以下文章可以帮助您:https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/ 为了使这个例子更容易编写,我使用listview,因为你基本上做的是创建一个列表。

XAML:

<StackLayout>

        <ListView x:Name="CategoriesList" ItemsSource="{Binding Categories}">

            <ListView.ItemTemplate>

                <DataTemplate>

                    <ViewCell>

                        <StackLayout HorizontalOptions="FillAndExpand"
                                     Padding="20,0,20,0"
                                     VerticalOptions="CenterAndExpand">

                            <StackLayout HorizontalOptions="StartAndExpand">

                                <Label Text="{Binding Name}" />

                            </StackLayout>

                            <StackLayout HorizontalOptions="StartAndExpand">

                                <Label Text="{Binding Count" />

                                <Image IsVisible="{Binding Selected}" Source="right1.png" />

                            </StackLayout>


                        </StackLayout>

                    </ViewCell>

                </DataTemplate>

            </ListView.ItemTemplate>

        </ListView>

    </StackLayout>

C#: 在页面的构造函数上添加对此mathod的调用: 还要确保将绑定上下文设置为视图模型!

public PageConstructor(PageViewModel viewModel)
        {
            this.BindingContext = viewModel;
            Listeners();
        }

private void Listeners()
        {
            CategoriesList.ItemTapped += (sender, e) =>
            {
                if (category.Selected == false)
                {
                    App.DB.UpdateSelected(true);
                }
                else
                {
                    App.DB.UpdateSelected(false);
                }
                categories = getCategories();
                totalPhraseCount = getTotalPhraseCount();
                Title = totalPhraseCount.ToString() + " phrases";
            };
        }

您的ViewModel应具有Categories属性并实现INotifyPropertyChanged接口:

ViewModel C#:

class PageViewModel : INotifyPropertyChanged
    {
        List<Category> Categories;
    public event PropertyChangedEventHandler PropertyChanged;

    public PageViewModel()
    {
        this.Categories = //API call to retrieve the categories
    }

    public List<Category> Categories
    {
        set
        {
            if (Categories != value)
            {
                Categories = value;

                if (PropertyChanged != null)
                {
                    PropertyChanged(this,
                        new PropertyChangedEventArgs("Categories"));
                }
            }
        }
        get
        {
            return Categories;
        }
    }
}

为了更好地实现MVVM模型,您可以尝试以下解决方案:

答案 2 :(得分:-1)

尝试以下

categories = getCategories();
foreach (var category in categories)
{
   var viewCell = new ViewCell 
   { 
      View = new StackLayout()
      {
         Padding = new Thickness(20, 0, 20, 0),
         HorizontalOptions = LayoutOptions.FillAndExpand,
         Children = { 
            new StackLayout() {
               Orientation = StackOrientation.Horizontal,
               VerticalOptions = LayoutOptions.CenterAndExpand,
               Children = {
                  new StackLayout() {
                     HorizontalOptions = LayoutOptions.StartAndExpand,
                     Children = {
                        new Label { Text = category.Name}
                      },
                  new StackLayout() {
                     HorizontalOptions = LayoutOptions.EndAndExpand,
                     Orientation = StackOrientation.Horizontal,
                     Children = {
                        new Label { Text = category.Count},
                        new Image { Source = "right1.png",
                                    IsVisible = category.Selected }
                     }
                  }
               }
            }
         }
       }
    };
    viewCell.Tapped += (sender, e) =>
    {
       if (category.Selected == false)
       {
          App.DB.UpdateSelected(true);
       }
       else
       {
          App.DB.UpdateSelected(false);
       }
       categories = getCategories();
       totalPhraseCount = getTotalPhraseCount();
       Title = totalPhraseCount.ToString() + " phrases";
     };

}
tableSection.Add(viewCell);
tableSection.ForceLayout();
// Or try tableview.Forcelayout();
// Or try parent_stacklayout.ForceLayout();