2016-12-22 4 views
15

Поэтому у меня есть следующий код, который создает ViewCells для моего TableView динамически:Как обновить данные TableView после нажатия ViewCell в форматах Xamarin?

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?

+0

Почему вы хотите использовать TableView? Ответ на этот вопрос важен для правильного решения. Если вы планируете иметь много строк в TableView, вам нужно будет проявить творческий подход к своему решению. Я хочу помочь, но вам нужно еще несколько советов о том, чего вы пытаетесь достичь в приложении с помощью этого TableView (например, это страница настроек или отображение динамических строк для пользователей и т. Д.). – BrewMate

ответ

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; 
    } 
} 

ViewModel:

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

Try После

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(); 
+0

Спасибо @Atul. Но это все еще не работает. Мой TableView по-прежнему не обновляется. –

+0

Можете ли вы прислать мне небольшой образец проекта, чтобы я мог сделать это за вас? – Atul

+0

Возможно ли это для вас? – Atul

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 должен обладать свойством категорий и реализуют интерфейс 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 вы можете попробовать следующие решения:

+0

Спасибо за предложение @Lucas. Я знаю, как это сделать в ListView, но мне было специально сказано использовать TableView, следовательно, мой вопрос. –

+0

Я не хочу быть раздражающим, но я не уверен, что TableView - это правильный путь для вас. Если вы посмотрите на документацию, в ней указано, что TableView следует использовать для статических данных, поэтому это свойство не имеет свойства ItemTemplate. Кроме того, это был дизайн, который будет использоваться для данных, которые представлены иначе, чем строка, строка, которая также не относится к вашему случаю. Документацию можно найти на странице https://developer.xamarin.com/guides/xamarin-forms/user-interface/tableview/#Use_Cases –

Смежные вопросы