Binding List of Items in WPF - c#

I try to realize MVVM. TextBox text in View is Binded to property itemName in Model.
On view is DataGrid -> Binded to ViewModel.Rows property
In ViewModel on itemName on change event run async request to remote service for products, which is goes to model SugestProducts property. SugestProducts property is source for ListView items.
If products more than 0 listview open. ListView SelectedItem is Binded to model product property.
I need on product selection in list view fill itemName property from Product.name property without request to remote service. Other work good.
My model is:
public class RowDocumentSaleWraper : INotifyPropertyChanged
{
private ObservableCollection<Product> _sugestProducts;
public ObservableCollection<Product> SugestProducts
{
get
{
return _sugestProducts;
}
set
{
_sugestProducts = value;
NotifyPropertyChanged("SugestProducts");
}
}
public Product product {get; set;}
_itemName
public override string itemName
{
get
{
return itemName;
}
set
{
itemName = value;
NotifyPropertyChanged("itemName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Product:
public class Product
{
public string name{get; set;}
}
My ViewModel Is:
public class OrderViewModel : DependencyObject
{
public ObservableCollection<RowDocumentSaleWraper> Rows { get; set; }
public OrderViewModel()
{
addNewRow();
}
internal void addNewRow()
{
RowDocumentSaleWraper row = new RowDocumentSaleWraper(Order);
row.PropertyChanged += row_PropertyChanged;
Rows.Add(row);
}
void row_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
RowDocumentSaleWraper row = sender as RowDocumentSaleWraper;
if (row != null && e.PropertyName == "itemName" && !String.IsNullOrEmpty(row.itemName))
{
//get products from remote service -> source for
requestProducts(row.itemName, row);
}
}
private async void requestProducts(string searchString, RowDocumentSaleWraper row)
{
if (!String.IsNullOrEmpty(searchString))
{
var products = await requestProductsAsync(searchString);
row.SugestProducts = listToObservable(products);
}
}
}
My Xaml:
<DataGrid Grid.Row="1" Name="mainDataGrid" ItemsSource="{Binding Rows , UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Product">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBox PreviewKeyDown="TextBox_PreviewKeyDown" KeyDown="TextBox_KeyDown" Text="{Binding itemName, UpdateSourceTrigger=PropertyChanged}" MinWidth="200"/>
<ListView ItemsSource="{Binding SugestProducts, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
KeyDown="ListView_KeyDown" SelectedItem ="{Binding product, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn DisplayMemberBinding="{Binding code}"/>
<GridViewColumn DisplayMemberBinding="{Binding name}" />
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

Based on the above comments, you should notify the ViewModel from the setter on itemName
public override string itemName
{
get
{
return itemName;
}
set
{
itemName = value;
NotifyPropertyChanged("itemName");
NotifyChange(itemName);
}
}
Then you'll define the event to retrieve the data
private async void NotifyChange(string name)
{
if (!String.IsNullOrEmpty(searchString))
{
var products = await requestProductsAsync(searchString);
SugestProducts = listToObservable(products);
}
}

Related

WPF listview item that binds to combobox

I know this question may have been asked before but I can't find a solution for my problem and I will need some help.
What I want to accomplish :
I want to bind the exposed property Values of each item (ParameterValues) in my ListView to the ComboBox column and have the exposed property SelectedValue as selected item.
What I have done:
public class MyViewModel : MvvmTemplate //MvvmTemplate implements InotifyPropertyChanged
{
private ObservableCollection<ParameterValues> _parameterValuesTest;
public ObservableCollection<ParameterValues> ParameterValuesTest
{
get => _parameterValuesTest;
set
{
if (value == null)
return;
_parameterValuesTest = value;
RaisePropertyChanged();
}
}
public MyViewModel()
{
Parameters = new List<ParametersModel>(GetParametersFromDatabase());
ParameterValuesTest = new ObservableCollection<ParameterValues>();
ParameterValuesTest.Clear();
foreach(var param in parameters)
{
ParameterValuesTest.Add(new ParameterValues(param));
}
}
}
Parameters model :
public class ParametersModel:MvvmTemplate
{
public ParametersModel()
{
Parameters = new Parameters();
}
public ParametersModel(Parameters Parameters)
{
Parameters = Parameters;
}
public Parameters Parameters { get; set; }
public int Id
{
get => Parameters.Id;
set
{
if (Parameters.Id == value)
{
return;
}
Parameters.Id = value;
RaisePropertyChanged();
}
}
public string Value1
{
get => Parameters.Value1;
set
{
if (Parameters.Value1 == value)
{
return;
}
Parameters.Value1 = value;
RaisePropertyChanged();
}
}
public string Value2
{
get => Parameters.Value2;
set
{
if (Parameters.Value2 == value)
{
return;
}
Parameters.Value2 = value;
RaisePropertyChanged();
}
}
}
Parameters values model :
public class ParameterValues:MvvmTemplate
{
public ParameterValues(ParametersModel parameter)
{
ParametersModel = parameter;
Values = new ObservableCollection<string>
{
"Default Value",
ParametersModel.Value1,
ParametersModel.Value2
};
SelectedValue = Values.First();
}
public ParametersModel ParametersModel { get; set; }
private ObservableCollection<string> _values;
public ObservableCollection<string> Values
{
get => _values;
set
{
if (_values == value)
return;
_values = value;
RaisePropertyChanged();
}
}
private string _selectedValue;
public string SelectedValue
{
get => _selectedValue;
set
{
if (_selectedValue == value)
return;
_selectedValue = value;
RaisePropertyChanged();
}
}
}
XAML:
<ListView ItemsSource="{Binding Path=ParameterValuesTest}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="Id" DisplayMemberBinding="{Binding ParametersModel.Id}"/>
<GridViewColumn Header="Value">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<ItemsControl ItemsSource="{Binding Values, NotifyOnTargetUpdated=True}" DisplayMemberPath="SelectedValue" Height="0"/>
<ComboBox ItemsSource="{Binding Values}" DisplayMemberPath="SelectedValue" SelectedValuePath="SelectedValue" SelectedValue="{Binding SelectedValue}" TextSearch.TextPath="SelectedValue" Text="{Binding SelectedValue}" IsEditable="True"/>
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Thanks in advance.
There are a few issues in your code.
In the parameters model, the assignment does not work, correct the parameter name.
public ParametersModel(Parameters parameters)
{
Parameters = parameters;
}
Remove the ItemsControl from the Grid, as it is hidden by the ComboBox or integrate it differently if you really need it, e.g. create rows or columns and place the controls in there.
The bindings in the ComboBox are wrong, you should bind to SelectedItem instead of using SelectedValue, since you have a collection of strings and not of a type that contains other properties that you want to bind to.
<ComboBox ItemsSource="{Binding Values}" SelectedItem="{Binding SelectedValue}" Text="{Binding SelectedValue}" IsEditable="True"/>
Remove the TextSearch attached property, as it is not used here.

How to get object of list after object's property has been updated in ListView

I'm making a ListView filled with List of objects, which properties are shown and editable in a ListView. I need to get object when its properties are being updated. How can I do this?
I tried creating an object of class and bind it to SelectedItem in ListView. The problem is that, obviously, the SelectedItem is set after clicking the row of ListItem, but not the children of that row. I need to get the updated object from the row of my ListView each time after any ComboBox or TextBox values are changed.
To handle all the things with INotifyPropertyChanged I'm using PropertyChanged.Fody. Could it help me to solve this problem easier?
View
Appearance of the ListView
<ListView
Margin="10"
Grid.Row="1"
Grid.ColumnSpan="2"
ItemsSource="{Binding TimesheetEntries}"
SelectedItem="{Binding SelectedEntry, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="30" Margin="3">
<TextBlock
Text="{Binding Date, StringFormat=dd-MM-yyyy}"
VerticalAlignment="Center"
Width="Auto"
Margin="10"/>
<ComboBox
SelectedValuePath="Key" DisplayMemberPath="Value"
ItemsSource="{Binding EmploymentTypesDictionary, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding SelectedEmployment, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Width="270"/>
<TextBox
Text="{Binding Hours, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="10,0,0,0"
Width="70"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel
public List<TimesheetEntryEntity> TimesheetEntries
{
get { return _TimesheetEntries; }
set { _TimesheetEntries = value; }
}
public TimesheetEntryEntity SelectedEntry
{
get { return _SelectedEntry; }
set { _SelectedEntry = value; }
}
...
private List<TimesheetEntryEntity> _TimesheetEntries { get; set; }
private TimesheetEntryEntity _SelectedEntry;
private TimesheetModel timesheetModel;
public TimesheetViewModel()
{
this.Timesheets = TimesheetUnitModel.GetAllTimesheetsForUnit((int)Application.Current.Properties["UnitID"]);
this._StartDate = DateTime.Now;
_TimesheetEntries = new List<TimesheetEntryEntity>();
}
public KeyValuePair<int, string> SelectedWorker
{
get { return _SelectedWorker; }
set
{
_SelectedWorker = value;
_TimesheetEntries =
timesheetModel.GetTimesheetList(_SelectedWorker.Key, SelectedTimesheet.Key, StartDate.Date);
}
}
TimesheetEntryEntity
public DateTime Date { get; set; }
public Dictionary<EmploymentTypes, string> EmploymentTypesDictionary { get; set; }
public EmploymentTypes SelectedEmployment {
get { return _SelectedEmployment; }
set
{
_SelectedEmployment = value;
CheckHoursAvaliability();
}
}
public bool HoursAvaliable { get; set; }
public decimal Hours
{
get;
set;
}
private EmploymentTypes _SelectedEmployment;
public TimesheetEntryEntity()
{
FillEmploymentTypes();
}
public void FillEmploymentTypes()
{
//Some code here
}
I tried to follow the answer from Get Object properties of selected list item question, but there were only textblocks, so the row gets selected anyway, but i have ComboBox and TextBox, who get their own focus.
You can implement INotifyPropertyChanged in your TimesheetEntryEntity i.e.
public abstract class TimesheetEntryEntity: INotifyPropertyChanged
{
public event EventHandler Changed;
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void OnChange()
{
EventHandler handler = Changed;
handler?.Invoke(this, EventArgs.Empty);
}
private DateTime date;
public DateTime Date
{
get => date;
set
{
if (date == value)
{
return;
}
//Do something with unchanged property
date = value;
RaisePropertyChanged();
OnChange();
//Do something with changed property
}
}
in your ViewModel before adding new item to list:
timesheet.Changed+=ItemChanged;
and
private void ItemChanged(object sender, EventArgs e)
{
var item=sender as TimesheetEntryEntity;
//do something
}

WPF Binding to three level ObservableCollection<T> property

I have 3 level subclasses with ObservableCollection<T> properties of each other. In MainViewModel I created ObservableCollection<Group> property which elements of Group class will be in first level in TreeView. In every Group class I created child ObservableCollection<Parameter> property. And in the end in Parameter class I created ObservableCollection<ParameterValue> for store values. Note: every class based on INotifyPropertyChanged interface. Let's to go the code.
Models.cs:
//BaseModel implement INotifyPropertyChanged
public class ParameterValue: BaseModel
{
private DateTime dateTimeValue;
public DateTime DateTimeValue
{
get { return dateTimeValue; }
set
{
dateTimeValue = value;
NotifyPropertyChanged("DateTimeValue");
}
}
private double value;
public double Value
{
get { return value; }
set
{
this.value = value;
NotifyPropertyChanged("Value");
}
}
}
//BaseModel implement INotifyPropertyChanged
public class Parameter: BaseModel
{
public Parameter()
{
values = new ObservableCollection<ParameterValue>();
}
private ObservableCollection<ParameterValue> values;
public ObservableCollection<ParameterValue> Values
{
get { return values; }
set
{
values = value;
NotifyPropertyChanged("Values");
}
}
private int parameterId;
public int ParameterId
{
get { return parameterId; }
set
{
parameterId = value;
NotifyPropertyChanged("ParameterId");
}
}
private string parameterName;
public string ParameterName
{
get { return parameterName; }
set
{
parameterName = value;
NotifyPropertyChanged("ParameterName");
}
}
}
//BaseModel implement INotifyPropertyChanged
public class Group: BaseModel
{
public Group()
{
parameters = new ObservableCollection<Parameter>();
}
private ObservableCollection<Parameter> parameters;
public ObservableCollection<Parameter> Parameters
{
get { return parameters; }
set
{
parameters = value;
NotifyPropertyChanged("Parameters");
}
}
private int groupId;
public int GroupId
{
get { return groupId; }
set
{
groupId = value;
NotifyPropertyChanged("Id");
}
}
private string groupName;
public string GroupName
{
get { return groupName; }
set
{
groupName = value;
NotifyPropertyChanged("GroupName");
}
}
}
//Implementing INotifyPropertyChanged
public class BaseModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ViewModels.cs:
//BaseModel implement INotifyPropertyChanged
public class MainViewModel: BaseModel
{
public MainViewModel()
{
groups = new ObservableCollection<Group>();
//fill sample data instead of recieving from DB
for (int i = 1; i < 11; i++)
{
Group group = new Group { GroupId = i, GroupName = "Group " + i.ToString()};
groups.Add(group);
for (int j = 1; j < 11; j++)
{
Parameter param = new Parameter { ParameterId = j, ParameterName = "Parameter "+j.ToString()};
for (int k = 1; k < 51; k++)
{
ParameterValue val = new ParameterValue { DateTimeValue = DateTime.Now.AddSeconds(i*j-k), Value = (1000-k*5)/((i+j)+1)};
param.Values.Add(val);
}
group.Parameters.Add(param);
}
}
int l = 0;
}
private ObservableCollection<Group> groups;
public ObservableCollection<Group> Groups
{
get { return groups; }
set
{
groups = value;
NotifyPropertyChanged("Groups");
}
}
}
And MainWindow.xaml in View role:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="75*" />
</Grid.ColumnDefinitions>
<TreeView x:Name="trv" Grid.Column="0" ItemsSource="{Binding Groups}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Parameters}">
<TextBlock Text="{Binding GroupName}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ParameterName}"></TextBlock>
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<ListView Grid.Column="1" Background="Bisque" ItemsSource="{Binding Path=Groups.Parameters}">
<ListView.View>
<GridView>
<GridViewColumn Header="Date Time" DisplayMemberBinding="{Binding DateTimeValue}"/>
<GridViewColumn Header="Value" DisplayMemberBinding="{Binding Value}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
In MainViewModel I simplify data receiving from DB replacing by nested for loops with test data.
I try to make showing selected in TreeView Parameter data in ListView in MVVM way.
In DataGroup necessary to create SelectedItem property of Parameter class for more accurate data recieving from DB? Of course in MVVM way.
In your ListView ItemSource you have to bind to the Values like so...
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="75*" />
</Grid.ColumnDefinitions>
<TreeView x:Name="trv" Grid.Column="0" ItemsSource="{Binding Groups}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Parameters}">
<TextBlock Text="{Binding GroupName}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ParameterName}"></TextBlock>
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<ListView Grid.Column="1"
Background="Bisque"
ItemsSource="{Binding SelectedItem.Values, ElementName=trv}">
<ListView.View>
<GridView>
<GridViewColumn Header="Date Time" DisplayMemberBinding="{Binding DateTimeValue}"/>
<GridViewColumn Header="Value" DisplayMemberBinding="{Binding Value}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
Observer how I binded to the SelectedItem of your TreeView. That selected item is expected to be the parameter which has property Values.
If you select Group than nothing will be displayed since Group does not have Values collection. Only Parameter has that.

WPF Binding DataGridCheckBoxColumn

I am having difficulty binding a DataGridCheckBoxColumn in a DataGrid in WPF.
What I am trying to do is have a "Select All" button to check all the items in the grid.
<Button Grid.Row="1" Grid.Column="0" Content="Select All In List" HorizontalAlignment="Stretch" Command="{Binding SelectAll}"></Button>
In my ViewModel I have a Command that is called from the button.
public ICommand SelectAll { get; set; }
private void OnSelectAll(object obj)
{
foreach (var item in EducationLeaflets)
{
item.Selected = true;
}
OnPropertyChanged("EducationLeaflets");
}
This is my property from my ViewModel that I bind my DataGrid to:
public ObservableCollection<LeafletListModel> EducationLeaflets { get; private set; }
My DataGrid with a DataGridCheckBoxColumn as the first column.
<DataGrid Grid.Row="0" Grid.Column="0"
AutoGenerateColumns="False"
EnableRowVirtualization="True"
ItemsSource="{Binding EducationLeaflets}"
RowDetailsVisibilityMode="VisibleWhenSelected"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Grid.ColumnSpan="3" Background="White" HorizontalGridLinesBrush="#FFF0F0F0" VerticalGridLinesBrush="#FFF0F0F0">
<DataGrid.Columns>
<DataGridCheckBoxColumn
Binding="{Binding Path=Selected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</DataGridCheckBoxColumn>
<DataGridTextColumn
Binding="{Binding Id}"
Header="RecordId"
Width="SizeToHeader" />
<DataGridTextColumn
Binding="{Binding Name}"
Header="Name"
Width="*" />
</DataGrid.Columns>
</DataGrid>
Also the model that is displayed in each grid row.
public class LeafletListModel: ListModel
{
public LeafletListModel(int id, string name, DateTime bpsDrugsUpdated):base(id, name)
{
BpsDrugsUpdated = bpsDrugsUpdated;
}
public bool Selected { get; set; }
public DateTime BpsDrugsUpdated { get;private set; }
}
When I click the button the items in the DataGrid are not checked as I would like. Thank you for your help.
It is not EducationLeaflets that changes - it stays the same ObservableCollection as before clicking SelectAll. Even its content does not change (this would be reflected in the CollectionChanged event from the ObservableCollection.
What actually changes are the individual items in the ObservableCollection. And since these do not implement INotifyPropertyChanged, the update will not be reflected in the Views.
So, if you make LeafletListModel implement INotifyPropertyChanged, it should
work as expected.
public class LeafletListModel: ListModel, INotifyPropertyChanged
{
private bool _selected;
public LeafletListModel(int id, string name, DateTime bpsDrugsUpdated):base(id, name)
{
BpsDrugsUpdated = bpsDrugsUpdated;
}
public bool Selected
{
get { return _selected; }
set
{
if (_selected != value)
{
_selected = value;
OnPropertyChanged();
}
}
}
public DateTime BpsDrugsUpdated { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

Color coding each row in a ListView

Let me start by saying that I am new to MVVM, so please bare with be, if the question is unclear let me know and I will try to clarify.
I have a button which is successfully binding a ListView. (it populates the listView).
below is the button VM code:
<Button Content="Fetch Data" Command="{Binding readFilesCommand}" CommandParameter="{Binding Path=Text, ElementName=browseFolderTextBox}" Name="button1" />
The listView which is being populated looks like this:
<ListView SelectionMode="Extended" Name="responseListView" ItemsSource="{Binding}" GridViewColumnHeader.Click="responseListViewClick" >
<ListView.Resources>
<local:IndexConverter x:Key="IndexConverter" />
<DataTemplate x:Key="OrdinalColumnDataTemplate">
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListViewItem},
Converter={StaticResource ResourceKey=IndexConverter}}" HorizontalAlignment="Right" />
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView x:Name="gridView2" AllowsColumnReorder="True">
<GridViewColumn Width="28" Header="#" CellTemplate="{StaticResource ResourceKey=OrdinalColumnDataTemplate}" />
<GridViewColumn Width="80" DisplayMemberBinding="{Binding Name}" Header="Name" />
<GridViewColumn Width="150" DisplayMemberBinding="{Binding EMail}" Header="EMail" />
<GridViewColumn Width="75" DisplayMemberBinding="{Binding Date}" Header="Date" />
<GridViewColumn Width="75" DisplayMemberBinding="{Binding Time}" Header="Time" />
</GridView>
</ListView.View>
</ListView>
Below is the code of the class being populated in the listView.
public class ResourceList : ObservableCollection<Resource>
{
public ResourceList() : base()
{
}
}
public class Resource : INotifyPropertyChanged
{
public Resource()
{
Name = "";
EMail = "";
Date = "";
Time = "";
SWList = new ObservableCollection<string>();
}
private string name;
private string eMail;
private string time;
private string date;
public string Name
{
get { return name;}
set
{
if(name != value)
{
name = value;
OnPropertyChanged("Name");
}
}
}
public string EMail
{
get { return eMail; }
set
{
if (eMail != value)
{
eMail = value;
OnPropertyChanged("EMail");
}
}
}
public string Date
{
get { return date;}
set
{
if (date != value)
{
date = value;
OnPropertyChanged("Date");
}
}
}
public string Time
{
get { return time; }
set
{
if (time != value)
{
time = value;
OnPropertyChanged("Time");
}
}
}
// This interface causes the View to be notified of changes to the instances of Resource.
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public ObservableCollection<string> SWList { get; set; }
}
// ObservableCollection notifies the View of changes to the collection (add, delete, move items)
public class Licenses : ObservableCollection<Licenses>
{
public Licenses()
{
}
public string Name { get; set; }
public string License { get; set; }
}
so far everything works fine. Now on to my question. I would like each row of the ListView to have a background color. lets say property time is missing for one row, then I would like the whole row to be red. Where should I start?
You can surround each ListViewItem with a container (do that with a template) and change the background color of this container with a binding or a DataTrigger.
One example here : Change background color of GridView row in a ListView
EDIT : according to MVVM, you should define a business property on your class Resource, of a type such boolean (IsValid ?) or enum (Status ?), and use a converter inside your Binding to convert the value to a SolidColorBrush (for example).

Categories

Resources