如何通过单击另一个列表视图 WPF 中的元素来刷新列表视图

Posted

技术标签:

【中文标题】如何通过单击另一个列表视图 WPF 中的元素来刷新列表视图【英文标题】:how to refresh a listview by clicking element in another listview WPF 【发布时间】:2021-12-23 21:34:55 【问题描述】:

我正在尝试编写一个 POS 系统。我想要两个列表,一个带有文章,当用户单击一篇文章时,该文章将添加到第二个列表中,并且列表会自动刷新。 这是我的代码

using Newtonsoft.Json;
    public class ArticlesDetailsViewModel : INotifyPropertyChanged, IArticleViewModel
    
        public ArticlesDetailsViewModel()
        
            string baseUrl = "http://api.market.csa.com/api/v1.1/Article/ListArticle";
            
            bool dr;
            using (HttpClient client = new HttpClient())
            
                var response = client.GetAsync(baseUrl);
                var result = response.Result;
                dr = result.IsSuccessStatusCode;
            if (dr)
            
                    string jsonstring = result.Content.ReadAsStringAsync().Result;
                    var articles = JsonConvert.DeserializeObject<ListArticleResponse>(jsonstring);
                    foreach(var art in articles.data)
                    
                        ListArticle.Add(art);
                        
                    
            
            else
            
                MessageBox.Show("Une erreur s'est produite lors de la recuration des articles, vérifiez votre connexion internet", "Error", MessageBoxButton.OK, MessageBoxImage.Error);

             

            
            //intializing ICollectionView using collection(ObservableCollection)
            ArticleCollection = CollectionViewSource.GetDefaultView(ListArticle);
            CommandeCollection = CollectionViewSource.GetDefaultView(ListCommande);




            ArticleCollection.Filter = Filter;
        
        private ObservableCollection<ArticleModel> _ListArticle = new ObservableCollection<ArticleModel>();

        public ObservableCollection<ArticleModel> ListArticle
        
            get  return _ListArticle; 
            set  _ListArticle= value;
                NotifyPropertyChanged("ListArticle");
            
        


        private ICollectionView _ArticleCollection;

        public ICollectionView ArticleCollection
        
            get  return _ArticleCollection; 
            set  _ArticleCollection= value;
                NotifyPropertyChanged("ArticleCollection");
            
        

        private ICollectionView _CommandeCollection;

        public ICollectionView CommandeCollection
        
            get  return _CommandeCollection; 
            set  _CommandeCollection=value;
                NotifyPropertyChanged("CommandeCollection");
            
        



        private bool Filter(object emp)
        
            ArticleModel employee = emp as ArticleModel;
            //you can write logic for filter here
            if (!string.IsNullOrEmpty(ArticleName) && !string.IsNullOrEmpty(ArticleCode))
                return employee.NomArticle.Contains(ArticleName) && employee.NomArticle.Contains(ArticleName);
            else if (string.IsNullOrEmpty(ArticleName))
                return employee.Code.Contains(ArticleCode);
            else
                return employee.NomArticle.Contains(ArticleName);
        

       
        private string _articleName = string.Empty;
        public string ArticleName
        
            get  return _articleName;
                
                
            set
            
                _articleName=value;
                NotifyPropertyChanged("ArticleName");
                ArticleCollection.Refresh();
            
        


        private string _articleCode = string.Empty;
        public string ArticleCode
        
            get  return _articleCode; 
            set
            
                _articleCode= value;
                NotifyPropertyChanged("ArticleCode");
                ArticleCollection.Refresh();
            
        


        private ArticleModel _ArticleSelected = new ArticleModel();
        public ArticleModel ArticleSelected
        
            get 
                return _ArticleSelected; 
            set
            
                _ArticleSelected=value;
                
                NotifyPropertyChanged("ArticleSelected");
            
        

        

        private ObservableCollection<ArticleModel> _ListCommande = new ObservableCollection<ArticleModel>();

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string property)
        
            if (PropertyChanged != null)
            
                PropertyChanged(this, new PropertyChangedEventArgs(property));
                PropertyChanged(this, new PropertyChangedEventArgs("CommandeCollection"));
            
        
        public ObservableCollection<ArticleModel> ListCommande
        
            get
            
                return _ListCommande;
            
            set
            
                _ListCommande= value;
                NotifyPropertyChanged("ListCommande");
            
        

    

命令列表的 xaml:

<UserControl
    x:Class="WantaMarketDesktop.View.CommandesListingView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:WantaMarketDesktop.View"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="0.5*"/>
        </Grid.ColumnDefinitions>


        <ListView ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ItemsSource="Binding CommandeCollection,UpdateSourceTrigger=PropertyChanged" Grid.ColumnSpan="2" >

            <ListView.View>

                <GridView  AllowsColumnReorder="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.CanContentScroll="True" >
                    <GridView.Columns>
                        <GridViewColumn Header=" ID" DisplayMemberBinding="Binding IdArticle"/>
                        <GridViewColumn Header="Nom" DisplayMemberBinding="Binding NomArticle"/>
                        <GridViewColumn Header="Quantite" DisplayMemberBinding="Binding Quantite"/>
                        <GridViewColumn Header="Prix" DisplayMemberBinding="Binding Prix"/>

                    </GridView.Columns>
                </GridView>
            </ListView.View>
        </ListView>
        <Label Grid.Row="1" Content="Montant total de la commande :   " FontSize="13"/>
        <Label Grid.Row="1" Grid.Column="1" FontWeight="SemiBold" Content="2750     XFA"  FontSize="17" Width="auto" VerticalAlignment="Center" HorizontalAlignment="Stretch" FontStyle="Normal"  />
    </Grid>
</UserControl>

xaml 文章列表

<UserControl x:Class="WantaMarketDesktop.View.ArticlesDetails"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WantaMarketDesktop.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,10,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="40"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="5">
            <TextBlock Text="Code  : " VerticalAlignment="Center" Margin="10,5,5,5"/>
            <TextBox Text="Binding ArticleCode,UpdateSourceTrigger=PropertyChanged" VerticalAlignment="Center" Width="200"/>

            <TextBlock Text="Nom  : " VerticalAlignment="Center" Margin="10,5,5,5"/>
            <TextBox Text="Binding ArticleName,UpdateSourceTrigger=PropertyChanged" VerticalAlignment="Center" Width="200"/>
        </StackPanel>


        <StackPanel Grid.Row="1" Margin="10,0">
            <Separator HorizontalAlignment="Stretch" Height="5" Margin="0,5,0,10"/>
            <!--setting ItemsSource of ListView to ICollectionView-->
            <ListView Cursor="Hand" ItemsSource="Binding ArticleCollection" SelectedItem="Binding ArticleSelected" HorizontalAlignment="Stretch" VerticalAlignment="Top" >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid  Columns="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ListView.ItemTemplate>
                    <DataTemplate >
                        <StackPanel Orientation="Vertical" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
                            <Image ToolTip="Binding Carracteristique"  Source="https://phonesdata.com/files/models/Xiaomi-Redmi-Note-10S-298.jpg" HorizontalAlignment="Stretch" VerticalAlignment="Top" Stretch="UniformToFill" MinHeight="50" MaxHeight="100"  />
                            <TextBlock Text="Binding NomArticle" ToolTip="Binding NomArticle" HorizontalAlignment="Stretch" FontSize="12" FontFamily="Franklin Gothic Medium" VerticalAlignment="Bottom" />
                            <WrapPanel Orientation="Horizontal" Margin="0,5,0,0">
                                <TextBlock  Text="Binding Prix"   HorizontalAlignment="Right" FontSize="11" FontFamily="Franklin Gothic Medium" VerticalAlignment="Bottom" />

                                <TextBlock Text="Binding Code" Margin="60,0,0,0"  HorizontalAlignment="Stretch" FontSize="9" FontFamily="Franklin Gothic Medium" VerticalAlignment="Center" />

                            </WrapPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
                
            </ListView>
           
        </StackPanel>
    </Grid>
</UserControl>

界面

public interface IArticleViewModel

    ObservableCollection<ArticleModel> ListArticle  get; set; 
    ObservableCollection<ArticleModel> ListCommande  get; set; 

现在我有这个

我想这样做,当我们点击文章图片时,文章会添加到左侧的列表中

【问题讨论】:

只需将 ArticleSelected 值添加到 ListCommande 集合中。 我做到了,当我检查代码时,我看到文章已添加,但列表没有刷新。 public ArticleModel ArticleSelected get return _ArticleSelected; 设置 _ArticleSelected=值; ListCommande.add(_ArticleSelected); NotifyPropertyChanged("ArticleSelected"); 如何设置每个UserControl的DataContext?两者必须共享视图模型类的相同实例。 是的,这就是我所做的 没有足够的信息来帮助您。我需要查看更多上下文。基本上它必须工作。您必须检查绑定是否有错误。也许数据上下文与预期不同。看看您如何设置数据上下文会很有趣,因为从当前行为看来,您正在对不同的模型实例进行操作。 【参考方案1】:

依赖于相同数据 (DataContext) 的所有控件必须共享视图模型类 (DataContext) 的相同实例,这一点很重要。

通常您不会明确设置DataContext。您使用 DataContext 继承,其中所有子元素都从其父元素隐式继承 DataContext

ArticlesDetailsViewModel 作为公共属性添加到您的MainViewModel。将MainViewModel 设置为MainWindowDataContext。然后让两个UserControl 元素的共同父级将其DataContext 绑定到MainViewModel(当前DataContext)的ArticlesDetailsViewModel 属性。

不要忘记从所有 UserControl 构造函数中删除 DataContext 赋值。

MainViewModel.cs

class MainViewModel : INotifyPropertyChanged

  // Shared instance
  public IArticleViewModel ArticlesDetailsViewModel  get; 

  public MainViewModel => this.ArticlesDetailsViewModel = new ArticlesDetailsViewModel();

MainWindow.xaml.cs

partial class MainWindow : Window

  public MainWindow()
  
    InitializeComponenet();
   
    this.DataContext = new MainViewModel();
  

MainWindow.xaml

<!-- DataContext is 'MainViewModel' ==> explcitly set -->
<Window>
    
  <!-- DataContext is 'MainViewModel' ==> inherited -->
  <StackPanel>
    
    <!-- DataContext is 'MainViewModel' ==> inherited -->
    <Button />
    
    <!-- DataContext is 'MainViewModel' ==> inherited -->
    <ListBox />
    
    <!-- DataContext is 'ArticlesDetailsViewModel' ==> explcitly set -->
    <StackPanel DataContext="Binding ArticlesDetailsViewModel">
    
      <!-- DataContext is 'ArticlesDetailsViewModel' ==> inherited -->
      <CommandesListingView />
    
      <!-- DataContext is 'ArticlesDetailsViewModel' ==> inherited -->
      <ArticlesDetails />
    </StackPanel>
  </StackPanel>
</Window>

【讨论】:

以上是关于如何通过单击另一个列表视图 WPF 中的元素来刷新列表视图的主要内容,如果未能解决你的问题,请参考以下文章

如何在按钮单击 FLUTTER 上刷新列表小部件数据

子视图中的 ListView 未正确刷新

单击列表视图中的某些项目时如何影响列表视图之外的元素?

从列表视图中删除一行后刷新片段

单击按钮刷新时如何刷新小部件列表视图?

如何刷新 WPF DataGrid?