i'm trying to code a POS system. i want to have two list, one with articles and when user click on an article the article is added to the second list and the list reflesh automatically. here is my code
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");
}
}
}
}
the xaml for the commande list:
<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>
the xaml article list
<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>
and the Interface
public interface IArticleViewModel
{
ObservableCollection<ArticleModel> ListArticle { get; set; }
ObservableCollection<ArticleModel> ListCommande { get; set; }
}
i want to do that when we click on article image , the article add to the list at the left
CodePudding user response:
It is esssential that all controls that depend on the same data (DataContext
) must share the same instance of the view model class (DataContext
).
Normally you don't set the DataContext
explicitly. You use DataContext
inheritance where all child elements implicitly inherit their DataContext
from their parent element.
Add ArticlesDetailsViewModel
as a public property to your MainViewModel
. Set the MainViewModel
as the DataContext
of the MainWindow
. Then let the common parent of both UserControl
elements bind its DataContext
to the ArticlesDetailsViewModel
property of the MainViewModel (current DataContext).
Don't forget to remove the DataContext
assignment from all UserControl
constructors.
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>