<ListView Name="listViewLoadDisableSchems" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.View>
<GridView>
<GridViewColumn >
<GridViewColumn.CellTemplate >
<DataTemplate >
<DataTemplate >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" >
<Label Name="lblSchemeID" VerticalAlignment="Center" Margin="0" Content="{Binding Id}" Visibility="Hidden" />
<CheckBox Name="chkScheme" VerticalAlignment="Center" Margin="0,0,0,0" Content="{Binding Name}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I want to get lblSchemeID if checkbox is selected. so i can update database.
How i can do it on butten click?
You need to look at some basic MVVM patterns to get this going. Try this in the XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding Items}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate >
<DataTemplate >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" >
<CheckBox VerticalAlignment="Center" Margin="0,0,0,0" Content="{Binding Name}" IsChecked="{Binding IsSelected}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Grid.Row="1" Content="What is checked?" Command="{Binding GoCommand}"></Button>
and your equivalent of this in the view model & code behind:
public class MainViewModel
{
public ObservableCollection<TestItem> Items { get; set; } = new ObservableCollection<TestItem> { new TestItem() { Id = 1, Name = "Foo" }, new TestItem() { Id = 2, Name = "Bar" } };
public ICommand GoCommand => new DelegateCommand(Go);
void Go()
{
MessageBox.Show(string.Join(Environment.NewLine, Items.Where(x => x.IsSelected).Select(x => x.Name)));
}
}
public class TestItem : INotifyPropertyChanged
{
private bool _isSelected;
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected
{
get { return _isSelected; }
set
{
if (value == _isSelected) return;
_isSelected = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
You can get an implementation of delegate command from Google. Ditto implementations of INotifyPropertyChanged if you struggle with that.
Related
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; }
}
for now i have this
i want to do that when we click on article image , the article add to the list at the left
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>
I am getting the values in my observable Collection in ViewModel Class but not getting the values displayed in my ComboBox please help
I referrred this link
https://www.c-sharpcorner.com/article/explain-combo-box-binding-in-mvvm-wpf/
XAML
<Window x:Class="MVVMDemo.UserRegistrationView"
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:viewmodel="clr-namespace:MVVMDemo"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<viewmodel:ViewModel x:Key="ViewModel"/>
<viewmodel:DatetimeToDateConverter x:Key="MyConverter"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource ViewModel}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Name" HorizontalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1" Width="100" HorizontalAlignment="Center" Text="{Binding Student.Name, Mode=TwoWay}" Margin="76,0"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Age" HorizontalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Width="100" HorizontalAlignment="Center" Text="{Binding Student.Age, Mode=TwoWay}"/>
<Button Content="Submit" Command="{Binding SubmitCommand}" HorizontalAlignment="Right" Grid.Row="4" Grid.Column="0" RenderTransformOrigin="0.61,1.96" Margin="0,27.348,0,159.452"/>
<ComboBox Grid.Column="1" ItemsSource="{Binding Path=FillCourseId}" Name="cmb_CourseIDName" HorizontalAlignment="Left" Margin="76,5,0,0"
Grid.Row="3" VerticalAlignment="Top" Width="120" Grid.RowSpan="2">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=CourseName}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Path=CourseID}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ListView ItemsSource="{Binding Students}" Grid.Row="4" Grid.Column="1" Width="200"
Margin="27.657,34.948,24.342,159.452">
<ListView.View >
<GridView >
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="60"/>
<GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}" Width="60"/>
<GridViewColumn Header="Joining Date" DisplayMemberBinding="{Binding JoiningDate, Converter={StaticResource MyConverter}}" Width="80" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
ViewModel Class here iam getting my values in my observableCollection FillCourseId after referring the link i mentioned iam still not able to get the values. please help !!!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Data;
namespace MVVMDemo
{
public class ViewModel : ViewModelBase, INotifyPropertyChanged
{
private Student _student;
private ObservableCollection<Student> _students;
private ICommand _SubmitCommand;
private ObservableCollection<Student> _fillCourseId = new ObservableCollection<Student>();
static String connectionString = #"Data Source=Ramco-PC\SQLEXPRESS;Initial Catalog=SIT_Ramco_DB;Integrated Security=True;";
SqlConnection con;
SqlCommand cmd;
// SqlDataAdapter adapter;
// DataSet ds;
//SqlDataReader reader;
public ObservableCollection<Student> FillCourseId
{
get { return _fillCourseId; }
set
{
_fillCourseId = value;
OnPropertyChanged("SystemStatusData");
}
}
public Student Student
{
get
{
return _student;
}
set
{
_student = value;
NotifyPropertyChanged("Student");
}
}
public ObservableCollection<Student> Students
{
get
{
return _students;
}
set
{
_students = value;
NotifyPropertyChanged("Students");
}
}
public ICommand SubmitCommand
{
get
{
if (_SubmitCommand == null)
{
_SubmitCommand = new RelayCommand(param => this.Submit(),
null);
}
return _SubmitCommand;
}
}
public void GetCourseIdFromDB()
{
try
{
con = new SqlConnection(connectionString);
con.Open();
cmd = new SqlCommand("select * from dev_Course", con);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter.Fill(dt);
// Student Student = new Student();
for (int i = 0; i < dt.Rows.Count; ++i)
FillCourseId.Add(new Student
{
CourseID = dt.Rows[i][0].ToString(),
CourseName =dt.Rows[i][1].ToString()
});
}
catch (Exception ex)
{
}
}
public ViewModel()
{
Student = new Student();
Students = new ObservableCollection<Student>();
Students.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Students_CollectionChanged);
}
void Students_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
NotifyPropertyChanged("Students");
}
private void Submit()
{
Student.JoiningDate = DateTime.Today.Date;
Students.Add(Student);
Student = new Student();
}
// Property Changed Event
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyname)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyname));
}
}
}
ModelClass i have defined my properties here
namespace MVVMDemo
{
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Course { get; set; }
public string CourseName { get; set; }
public string CourseID { get; set; }
App.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainWindow = new Window();
var viewModel = new ViewModel();
mainWindow.DataContext = viewModel;
viewModel.GetCourseIdFromDB();
mainWindow.Show();
//viewModel.GetCourseIdFromDB();
}
}
Don't set the DataContext of the Grid to your ViewModel resource like this:
<Grid DataContext="{Binding Source={StaticResource ViewModel}}">
Remove the resource itself as well:
<viewmodel:ViewModel x:Key="ViewModel"/>
I tried this and this which fulfilled my requirement of getting data displayed from Observable collections to combobox with "-" separated values.
<ComboBox Grid.Column="1" ItemsSource="{Binding FillCourseId}" Name="cmb_CourseIDName" HorizontalAlignment="Left" Margin="164.191,5,0,0"
Grid.Row="3" VerticalAlignment="Top" Width="168.342" Grid.RowSpan="2" DataContext="{Binding Source={StaticResource ViewModel}}" FontSize="8" IsReadOnly="True"
SelectedValue="{Binding Student.SCourseIDName,Mode=TwoWay}" RenderTransformOrigin="1.431,0.77">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Path=CourseName, Mode=TwoWay}" FontSize="12"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Path=CourseID, Mode=TwoWay}" FontSize="12"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
and i called my function GetCourseIdFromDB() in a Constructor in ViewModel Class. Thanks for pointing this out it really solved my problem.
public ViewModel()
{
Student = new Student();
Students = new ObservableCollection<Student>();
Students.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Students_CollectionChanged);
GetCourseIdFromDB();
}
I have the following XAML
<Label Content="Player Name" Grid.Row="0" Grid.Column="0" Margin="2,0,2,0" HorizontalAlignment="Right" Foreground="White"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="2,2,2,2" Text="{Binding PlayerFirstName}"/>
<Label Content="Player Last Name" Grid.Row="1" Grid.Column="0" Margin="2,0,2,0" HorizontalAlignment="Right" Foreground="White"/>
<TextBox Grid.Row="1" Grid.Column="1" Margin="2,2,2,2" Text="{Binding PlayerLastName}"/>
<Label Content="Player College" Grid.Row="2" Grid.Column="0" Margin="2,0,2,0" HorizontalAlignment="Right" Foreground="White"/>
<ComboBox Grid.Row="2" Grid.Column="1" Margin="2,2,2,2"
ItemsSource="{Binding Colleges}" DisplayMemberPath="CollegeName"
SelectedItem="{Binding SelectedCollege}"/>
<Button Content="Add Player" Grid.Row="3" Grid.Column="1" Width="75" Margin="2,2,2,2"
Background="Blue" Foreground="White" HorizontalAlignment="Right"
Command="{Binding NewPlayer}"/>
<ListView Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="1" Margin="2,2,2,2"
ItemsSource="{Binding Players, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Header="First Name" Width="100" DisplayMemberBinding="{Binding First}"/>
<GridViewColumn Header="Last Name" Width="100" DisplayMemberBinding="{Binding Last}"/>
<GridViewColumn Header="College" Width="100" DisplayMemberBinding="{Binding College}"/>
</GridView>
</ListView.View>
</ListView>
Which is bound to my PlayersViewModel Class
public class PlayersViewModel : ObservableObject
{
#region Variables
private DataView _Players = Controller.PlayerView.GetData().DefaultView;
private DataView _Colleges = Controller.CollegeTableAdapter.GetData().DefaultView;
private string _PlayerFirstName;
private string _PlayerLastName;
private DataRowView _SelectedCollege;
private long _PlayerCollegeID;
#endregion
#region Bindings
public DataView Players
{
get
{
return _Players;
}
set
{
_Players = value;
RaisePropertyChangedEvent("Players");
}
}
public DataView Colleges
{
get { return _Colleges; }
set
{
_Colleges = value;
RaisePropertyChangedEvent("Colleges");
}
}
public string PlayerFirstName
{
get { return _PlayerFirstName; }
set
{
_PlayerFirstName = value;
RaisePropertyChangedEvent("PlayerFirstName");
}
}
public string PlayerLastName
{
get { return _PlayerLastName; }
set
{
_PlayerLastName = value;
RaisePropertyChangedEvent("PlayerLastName");
}
}
public DataRowView SelectedCollege
{
get { return _SelectedCollege; }
set
{
_SelectedCollege = value;
_PlayerCollegeID = _SelectedCollege.Row.Field<long>("CollegeID");
RaisePropertyChangedEvent("SelectedCollege");
}
}
public ICommand NewPlayer
{
get { return new DelegateCommand(AddPlayer); }
}
#endregion
#region Methods
private void AddPlayer()
{
Controller.PersonTableAdapter.InsertPerson(_PlayerFirstName, _PlayerLastName, _PlayerCollegeID);
Players = Controller.PlayerView.GetData().DefaultView;
}
#endregion
}
This all works great, except when I run the InsertPerson Query in my PersonTableAdapter (which works manually and I've proven to work from the program), The Players ListView doesn't update after adding a new entry.
I found out what I did wrong.
Always make sure you are Implementing the INotifyPropertyChanged Interface in your ObservableObject Class
Mine looks like this now:
public abstract class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
In my Application I've got a Dictionary with int as key and ObservableCollection as value:
Dictionary<int, ObservableCollection<Entity>> SourceDict { get; set; }
Now I want to bind the Dictionary to a Datagrid where all ObservableCollections of this Dictionary should be presented.
If I bind it like this:
ItemsSource="{Binding SourceDict}"
I get a empty Datagrid. Is there a way to do this or before binding should I convert the Dictionary to an ObservableCollection?
<Grid>
<ListView HorizontalAlignment="Center" Width="525" Margin="0,42,0,52" ItemsSource="{Binding SourceList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView x:Name="gv_Listview">
<GridViewColumn Header="Age">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness=".3" Margin="-6,-3">
<TextBlock TextAlignment="Center" Text="{Binding Age}" Height="30" Margin="6,3" Width="90"/>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness=".3" Margin="-6,-3">
<TextBlock x:Name="txtAriza" TextAlignment="Center" Text="{Binding Name}" TextWrapping="Wrap" Height="30" Margin="6,3" Width="112"/>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Surname">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness=".3 .3 .0 .3" Margin="-6,-3">
<TextBlock TextAlignment="Center" Text="{Binding Surname}" Height="30" Margin="6,3" Width="60"/>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
this is the TestEntity
public class TestEntity : INotifyPropertyChanged
{
private string _name ;
private string _surname;
private int _age ;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged("Name"); }
}
public int Age
{
get { return _age; }
set { _age = value; OnPropertyChanged("Age"); }
}
public string Surname
{
get { return _surname; }
set { _surname = value; OnPropertyChanged("Surname"); }
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
And DataContext
private List<ObservableCollection<TestEntity>> _source = new List<ObservableCollection<TestEntity>>();
public List<ObservableCollection<TestEntity>> SourceList
{
get { return _source; }
set { _source = value; }
}
public DataContext()
{
this.SourceList.Add(new ObservableCollection<TestEntity> { new TestEntity { Age = 21 , Name = "Chris" , Surname = "James"}});
this.SourceList.Add(new ObservableCollection<TestEntity> { new TestEntity { Age = 23, Name = "Jin", Surname = "Evelin" } });
this.SourceList.Add(new ObservableCollection<TestEntity> { new TestEntity { Age = 33, Name = "Ryan", Surname = "Thrusty" } });
this.SourceList.Add(new ObservableCollection<TestEntity> { new TestEntity { Age = 34, Name = "Martin", Surname = "Riggs" } });
}
Hope this helps.
I have the following requirements:
Window will show a ListView with multiple items.
User should be able to check (Checkbox) any item.
a) If one item, all items should be unchecked and disabled.
b) If checked item is unchecked, than all items should be enabled.
As of now, I have the following incomplete code.
MainWindow XAML:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="520.149" Width="732.463">
<Window.Resources>
<ResourceDictionary Source="MainWindowResource.xaml" />
</Window.Resources>
<Grid>
<ListView x:Name="myListBox" ItemTemplate="{StaticResource OfferingTemplate}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3" VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
</Window>
DataTemplete for ListView:
<DataTemplate x:Key="OfferingTemplate">
<StackPanel>
<Grid IsEnabled="{Binding IsEnabled}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8"></ColumnDefinition>
<ColumnDefinition Width="120"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Rectangle Grid.Column="0" Grid.RowSpan="3" Fill="#F4CA16" />
<Label
Grid.Column="1"
Grid.Row="0"
Content="{Binding Title}"
FontSize="18" FontWeight="Bold"
Margin="0,0,0,0" />
<TextBlock
Grid.Column="1"
Grid.Row="1"
FontSize="10"
Text="{Binding Description}"
Foreground="Black"
TextWrapping="WrapWithOverflow"
Margin="5,0,0,0" />
<CheckBox
Grid.Column="1"
Grid.Row="2"
FontSize="14"
IsChecked="{Binding IsSelected}"
VerticalAlignment="Bottom"
Margin="5,0,0,0">
<TextBlock Text="Select" Margin="0,-2,0,0"/>
</CheckBox>
</Grid>
</StackPanel>
</DataTemplate>
Model:
class MyModel
{
public string Title { get; set; }
public string Description { get; set; }
public bool IsSelected { get; set; }
public bool IsEnabled { get; set; }
}
ViewModel:
class MyViewModel : INotifyPropertyChanged
{
private MyModel offering;
public MyViewModel()
{
offering = new MyModel();
}
public int ID { get; set; }
public string Title
{
get { return offering.Title; }
set
{
offering.Title = value;
RaisePropertyChanged("Title");
}
}
public string Description
{
get { return offering.Description; }
set
{
offering.Description = value;
RaisePropertyChanged("Description");
}
}
public bool IsSelected
{
get { return offering.IsSelected; }
set
{
offering.IsSelected = value;
RaisePropertyChanged("IsSelected");
}
}
public bool IsEnabled
{
get { return offering.IsEnabled; }
set
{
offering.IsEnabled = value;
RaisePropertyChanged("IsEnabled");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
This is an interesting question. Since the action you want applies to all items in the list, this logic should in list class level. Your MyViewModel class is fine. You need add some logic in your list class and XAML but thanks to Prism, it is quite easy.
The list class (not shown in your post) Contains:
public ObservableCollection<MyViewModel> MyItems { get; set; } //Binding to ItemsSource
private ICommand _selectCommand;
public ICommand SelectCommand
{
get { return _selectCommand ?? (_selectCommand = new DelegateCommand<MyViewModel>(DoSelect)); }
}
private void DoSelect(MyViewModel myViewModel)
{
foreach(var item in MyItems)
if (item != myViewModel)
{
item.IsSelected = false;
item.IsEnabled = false;
}
}
private ICommand _unselectCommand;
public ICommand UnselectCommand
{
get { return _unselectCommand ?? (_unselectCommand = new DelegateCommand<MyViewModel>(DoUnselect)); }
}
private void DoUnselect(MyViewModel myViewModel)
{
foreach (var item in MyItems)
if (item != myViewModel)
{
item.IsEnabled = true;
}
}
There are two commands, one for selecting and the other for unselecting. The magic is on XAML:
<ListView ItemsSource="{Binding Path=MyItems}" x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsSelected}" IsEnabled="{Binding Path=IsEnabled}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ElementName=listView, Path=DataContext.SelectCommand}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding ElementName=listView, Path=DataContext.UnselectCommand}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Using Prism's triggers, you can map CheckBox's Checked and Unchecked event to your list view model's commands and passing the item view model as parameter.
It is working perfectly but one thing is annoying, that setting item's IsSelected is separate. When you check a CheckBox, the item behind is set to true through DataBinding but all others are set through parent view model. If your post is all your requirement, you can remove IsChecked binding and put the logic of setting one IsSelected inside list view model, which looks clenaer and easier to write test code.