как обновить представление списка, щелкнув элемент в другом представлении списка WPF

#c# #wpf #listview #data-binding #observablecollection

Вопрос:

я пытаюсь закодировать систему 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.Resu<
                dr = result.IsSuccessStatusCode;
            if (dr)
            {
                    string jsonstring = result.Content.ReadAsStringAsync().Resu<
                    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) amp;amp; !string.IsNullOrEmpty(ArticleCode))
                return employee.NomArticle.Contains(ArticleName) amp;amp; 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; }
}
 

на данный момент у меня есть это
введите описание изображения здесь

я хочу сделать это , когда мы нажимаем на изображение статьи, статья добавляется в список слева

Комментарии:

1. Просто добавьте выбранное значение Articles в коллекцию ListCommande.

2. я сделал это, и когда я просматриваю код, я вижу, что статья была добавлена, но список не обновляется. public ArticleModel ArticleSelected { получить { вернуть _ArticleSelected; } установить { _ArticleSelected=значение; ListCommande.add(_ArticleSelected); NotifyPropertyChanged(«Избранные статьи»); } }

3. Как вы устанавливаете DataContext каждого пользовательского элемента управления? Существенно, что оба они используют один и тот же экземпляр класса модели представления.

4. да, это то, что я сделал

5. Информации недостаточно, чтобы помочь вам больше. Мне нужно было бы увидеть больше контекста. В принципе, это должно сработать. Вы должны проверить привязки на наличие ошибок. Возможно, контекст данных отличается от ожидаемого. Было бы интересно посмотреть, как вы задаете контекст данных, потому что из текущего поведения видно, что вы работаете с разными экземплярами модели.

Ответ №1:

Существенно, что все элементы управления, зависящие от одних и тех же данных ( DataContext ), должны совместно использовать один и тот же экземпляр класса модели представления ( DataContext ).

Обычно вы не устанавливаете DataContext это явно. Вы используете DataContext наследование, когда все дочерние элементы неявно наследуют их DataContext от родительского элемента.

Добавьте ArticlesDetailsViewModel в качестве публичной собственности к своему MainViewModel . Установите MainViewModel как то DataContext из того MainWindow . Затем пусть общий родитель обоих UserControl элементов свяжет его DataContext со ArticlesDetailsViewModel свойством MainViewModel (текущий DataContext).

Не забудьте удалить DataContext назначение из всех UserControl конструкторов.

MainViewModel.cs

 class MainViewModel : INotifyPropertyChanged
{
  // Shared instance
  public IArticleViewModel ArticlesDetailsViewModel { get; }

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

Главное окно.xaml.cs

 partial class MainWindow : Window
{
  public MainWindow()
  {
    InitializeComponenet();
   
    this.DataContext = new MainViewModel();
  }
}
 

Главное окно.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>