【问题标题】:Xamarin Forms not updating ListViewXamarin Forms 不更新 ListView
【发布时间】:2019-04-23 04:26:56
【问题描述】:

我的 PropertyChanged 事件未在 xamarin 中更新我的列表视图。 有人可以帮我吗?

当搜索栏文本发生变化时,会触发 RefreshListView 方法。

我的视图模型:

public class LebensmittelViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Lebensmittel> lebensmittelList = new ObservableCollection<Lebensmittel>();
    public List<Lebensmittel> normalLebensmittelList = new List<Lebensmittel>();
    public event PropertyChangedEventHandler PropertyChanged;

    public LebensmittelViewModel()
    {
        normalLebensmittelList = App.LebensmittelDatabase.getAllLebensmittel();
    }

    public void RefreshListView(string searchBarText)
    {
        LebensmittelList = addItemInCollection(searchBarText);
    }

    public ObservableCollection<Lebensmittel> addItemInCollection(string searchBarText)
    {
        if (searchBarText != null)
        {
            foreach (var item in normalLebensmittelList)
            {
                if (item.Name.Contains(searchBarText) || item.Name.Contains(searchBarText.First().ToString().ToUpper()))
                {
                    LebensmittelList.Add(item);
                };
            }
        }
        return LebensmittelList;
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public ObservableCollection<Lebensmittel> LebensmittelList
    {
        get
        {
            return lebensmittelList;
        }
        set
        {
            lebensmittelList = value;
            OnPropertyChanged("LebensmittelList");
        }
    }
}

Einkaufsliste.xaml

<ContentPage.Content>
    <StackLayout Spacing="10" Padding="10">
        <SearchBar x:Name="searchBar" Text="{Binding searchBarText}" Placeholder="Lebensmittel suchen..." VerticalOptions="StartAndExpand">
            <SearchBar.Behaviors>
                <behavior:TextChangedBehavior/>
            </SearchBar.Behaviors>
        </SearchBar>
        <ListView x:Name="listView" ItemsSource="{Binding LebensmittelList}" HasUnevenRows="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal" Padding="10">
                            <Label Text="{Binding Name}" YAlign="Center" Font="Large"/>
                            <ia:Checkbox HorizontalOptions="EndAndExpand"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage.Content>

Einkaufsliste.xaml.cs

public Einkaufsliste ()
    {
        InitializeComponent ();
        BindingContext = new LebensmittelViewModel();
    }

我认为一切都应该没问题,但它不起作用。 希望有人可以帮助我,

谢谢

为汤姆编辑:

public void RefreshListView(string searchBarText)
    {
        addItemInCollection(searchBarText);
    }

    public void addItemInCollection(string searchBarText)
    {
        if (searchBarText != null)
        {
            foreach (var item in normalLebensmittelList)
            {
                if (item.Name.Contains(searchBarText) || item.Name.Contains(searchBarText.First().ToString().ToUpper()))
                {
                    AddItemToList(item);
                };
            }
        }
    }

    private void AddItemToList(Lebensmittel item)
    {
        lebensmittelList.Add(item);
        LebensmittelList = lebensmittelList;
    }

【问题讨论】:

    标签: c# listview xamarin xamarin.forms


    【解决方案1】:

    它是如何实现行为TextChangedBehavior的?您是否将BindingContext 转换为LebensmittelViewModel 以便调用RefreshListView?

    我会摆脱这种行为:/ 并添加一个TextChanged 事件,创建属性SearchBarText,因为我看不到它的声明位置并且您将它绑定到SearchBar,重构RefreshListView 方法...我认为它应该可以工作... :)

    Einkaufsliste.xaml.cs

    private LebensmittelViewModel vm = new LebensmittelViewModel();
    public Einkaufsliste ()
    {
        InitializeComponent ();
        BindingContext = vm;
    }
    
    public void OnSeachBarTextChange(object e, TextChangedEventArgs args)
    {
        vm.RefreshListView();
    }
    

    Einkaufsliste.xaml

    <ContentPage.Content>
        <StackLayout Spacing="10" Padding="10">
            <SearchBar x:Name="searchBar" Text="{Binding SearchBarText, Mode=TwoWay}" Placeholder="Lebensmittel suchen..." VerticalOptions="StartAndExpand" TextChanged="OnSeachBarTextChange">
            </SearchBar>
            <ListView x:Name="listView" ItemsSource="{Binding LebensmittelList}" HasUnevenRows="True">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal" Padding="10">
                                <Label Text="{Binding Name}" YAlign="Center" Font="Large"/>
                                <ia:Checkbox HorizontalOptions="EndAndExpand"/>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
    

    视图模型

    private string _searchBarText;
    
    public string SearchBarText
    {
        get
        {
            return _searchBarText;
        }
        set
        {
            _searchBarText = value;
            OnPropertyChanged("SearchBarText");
        }
    }
    
    public void RefreshListView()
    {
        if (!string.IsNullOrEmpty(searchBarText))
        {
            var matches = normalLebensmittelList.Where(x => x.Name.Contains(searchBarText) || x.Name.Contains(searchBarText.First().ToString().ToUpper())
            foreach (var item in matches)
            {
              LebensmittelList.Add(item);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以尝试替换以下方法吗:

      public void RefreshListView(string searchBarText)
      {
          LebensmittelList.Clear();
          addItemInCollection(searchBarText);
      }
      

      由于您已经在使用 Observable 集合,因此您不需要替换该集合。您可以添加,它会自动观察和绑定。让我知道它是否有效!

      【讨论】:

      • 感谢您的快速回复,但这不起作用:/
      【解决方案3】:

      您似乎对LebensmittelList 有额外的工作。尝试执行以下操作:

      public void RefreshListView(string searchBarText)
      {
          // this can be list clearing, if you need it
          addItemInCollection(searchBarText);
          OnPropertyChanged("LebensmittelList");
      }
      
      public void addItemInCollection(string searchBarText)
      {
          if (searchBarText != null)
          {
              foreach (var item in normalLebensmittelList)
              {
                  if (item.Name.Contains(searchBarText) || item.Name.Contains(searchBarText.First().ToString().ToUpper()))
                  {
                      LebensmittelList.Add(item);
                  };
              }
          }
      }
      

      编辑: 我不知道是否有人可以将此解决方案称为优雅,但它应该可以工作。

      internal class MyCollection<T> : ObservableCollection<T> 
      {
          public void DoCollectionChanged()
          {
              OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
          }
      
      }
      
          ... MyCollection<LebensmittelItem> LebensmittelList; // field and property declaration should be changed
      
      public void RefreshListView(string searchBarText)
      {
          // this can be list clearing, if you need it
          addItemInCollection(searchBarText);
          LebensmittelList.DoCollectionChanged();
      }
      

      【讨论】:

        【解决方案4】:

        当您执行RefreshListView 时,属性set 中的OnPropertyChanged 是否被调用?

        【讨论】:

        • 是的,它进去了,它也跳进去了,但没有任何效果
        【解决方案5】:

        在addItemToCollection 方法中,您正在调用以下行:

        LebensmittelList.Add(item);
        

        在这种情况下,LebensmittelList 是一个属性,而不是变量。 LebensmittelList.Add(item); 行有效地执行了以下操作:

        var temporaryList = LebensmittelList; // Gets lebensmittelList and assigns to temporaryList
        temporaryList.Add(item); // You add the item to the *variable temporaryList*
        

        本质上,您添加的是lebensmittelList(临时副本)的实例,而不是lebensmittelList 变量。将该项目添加到临时列表后,整个(临时)列表将被丢弃而不“保存更改”。

        要真正更新LebensmittelList,最好调用如下方法:

        private void AddItemToList(object item)
        {
            lebensmittelList.Add(item);
            LebensmittelList = lebensmittelList;
        }
        

        【讨论】:

        • 不幸的是不起作用:/我可以将整个项目上传到某个地方
        • 我在原帖中为你添加了它
        猜你喜欢
        • 1970-01-01
        • 2016-10-03
        • 2018-10-16
        • 1970-01-01
        • 2018-10-13
        • 1970-01-01
        • 2016-09-24
        • 1970-01-01
        • 2017-01-05
        相关资源
        最近更新 更多