滑动时如何动态添加FlipView项目(文本内容)?

How to dynamic add FlipView item (text content) when swipe?

我想在 UWP 中动态添加新的翻转视图项目。这样我就可以将无限项添加到我的翻转视图中。比如抓取热点新闻,在翻页中一一展示。

从网上找了一些类似的代码,稍微修改了一下。下面是后面的xaml代码和cs代码。如您所见,我想使用 FlipView_SelectionChanged() 动态添加新的翻转视图项目但失败了。我希望添加带有 Name new 3Name new 4...

等文本内容的新翻转视图项目

XAML:

<Grid Name="grid">
    <FlipView Name="flipView" ItemsSource="{Binding ModelItems}">
        <FlipView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Name}" FontSize="60" />
                </StackPanel>
            </DataTemplate>
        </FlipView.ItemTemplate>
    </FlipView>
</Grid>

C#:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        flipView.SelectionChanged += FlipView_SelectionChanged;
    }

    private void FlipView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        Debug.WriteLine("flipview selection changed...index = " + flipView.SelectedIndex);

        BaseViewModel bv = new BaseViewModel();
        bv.ModelItems.Add(new BaseViewModelItem() { Name = "Name new " + flipView.SelectedIndex });

        //grid.DataContext = bv;

        Debug.WriteLine("flipview selection changed...count = " + bv.ModelItems.Count);
    }

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        grid.DataContext = new BaseViewModel();
    }

    public class BaseViewModelItem
    {
        public string Name { get; set; }
    }

    public class BaseViewModel
    {
        public ObservableCollection<BaseViewModelItem> ModelItems { get; set; }
        public BaseViewModel()
        {
            ModelItems = new ObservableCollection<BaseViewModelItem>();
            ModelItems.Add(new BaseViewModelItem() { Name = "Name 1" });
            ModelItems.Add(new BaseViewModelItem() { Name = "Name 2" });
            ModelItems.Add(new BaseViewModelItem() { Name = "Name 3" });
        }
    }
}

这里有两件事在起作用。首先,您不需要分配整个视图模型的新实例来进行更改 - 相反,您可以只检索现有视图模型并添加新项目:

var vm = (BaseViewModel)grid.DataContext;
bv.ModelItems.Add(
    new BaseViewModelItem() { 
      Name = "Name new " + flipView.SelectedIndex 
    });

那么附加事件的时间就有问题了。如果您在构造函数中附加它,它将在第一次设置 DataContext 并且将项目添加到 ObservableCollection 时立即触发 - 并尝试在这一刻添加项目会让你以灾难性的失败告终。相反,您应该仅在设置 DataContext 之后附加事件 - 因此从构造函数中删除 flipView.SelectionChanged += FlipView_SelectionChanged;OnNavigatedTo after 设置数据上下文:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    grid.DataContext = new BaseViewModel();
    flipView.SelectionChanged += FlipView_SelectionChanged;
}

这样的方式将在更改选择时正确添加项目。

我已经修改了您分享的代码。我建议您使用数据绑定而不是 FlipView_SelectionChanged(),只要将项目添加到 ModelItems,它就会更新它所绑定的元素。我希望这会有所帮助。

<Grid Name="grid">
    <Grid.RowDefinitions>
        <RowDefinition Height="20"/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Grid Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" Content="Add New FlipView Item" Click="Button_Click"/>
        <DockPanel Grid.Column="1">
            <TextBlock>Flipview Item Count : </TextBlock>
            <TextBlock Text="{Binding ModelItems.Count}"/>
        </DockPanel>
    </Grid>

    <FlipView Grid.Row="1" Name="flipView" ItemsSource="{Binding ModelItems,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
        <FlipView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <DockPanel>
                        <TextBlock Text="Index:" FontSize="20"/>
                        <TextBlock Text="{Binding Index}" FontSize="60" />
                    </DockPanel>
                    <DockPanel>
                        <TextBlock Text="Name:" FontSize="20"/>
                        <TextBlock Text="{Binding Name}" FontSize="60" />
                    </DockPanel>
                </StackPanel>
            </DataTemplate>
        </FlipView.ItemTemplate>
    </FlipView>
</Grid>

逻辑部分代码

//Interaction logic for MainWindow.xaml
public partial class MainWindow : Window
{
    public BaseViewModel ViewModel { get; set; } = new BaseViewModel();

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = ViewModel;
    }

    static int k = 3;
    private void Button_Click(object sender, RoutedEventArgs e) //can also implement using ICommand instead of event
    {
        this.ViewModel.ModelItems.Add(new BaseModelItem { Index = k, Name = "Name" + ++k });
    }
}

//--------Model------------
public class NotifyPropertyChanged : System.ComponentModel.INotifyPropertyChanged
{
    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyRaised(string propertyname)
    {
        PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyname));
    }
}

public class BaseModelItem : NotifyPropertyChanged
{
    string _name = string.Empty;
    public string Name
    {
        get { return _name; }
        set { _name = value; OnPropertyRaised("Name"); }
    }

    int _index = 0;
    public int Index
    {
        get { return _index; }
        set { _index = value; OnPropertyRaised("Index"); }
    }
}

//--------ViewModel------------
public class BaseViewModel:NotifyPropertyChanged
{
    System.Collections.ObjectModel.ObservableCollection<BaseModelItem> _modelItems = new System.Collections.ObjectModel.ObservableCollection<BaseModelItem>();
    public System.Collections.ObjectModel.ObservableCollection<BaseModelItem> ModelItems
    {
        get { return _modelItems; }
        set { _modelItems = value; OnPropertyRaised("ModelItems"); }
    }

    public BaseViewModel()
    {
        ModelItems = new System.Collections.ObjectModel.ObservableCollection<BaseModelItem>();
        ModelItems.Add(new BaseModelItem() { Name = "Name 1", Index = 0 });
        ModelItems.Add(new BaseModelItem() { Name = "Name 2", Index = 1 });
        ModelItems.Add(new BaseModelItem() { Name = "Name 3", Index = 2 });
    }
}