Dynamically Add Custom Control with Binding ObservableCollection - wpf

I am tring to add Custom controls(live chart) by using stack panel dynamically.
I have tried many times with below code and just text datas it looks fine but piechart does not.
when run as like below VS Designer hangs.
If someone have experience about this, any help would be appreciated.
In XAML
<ItemsControl Grid.Row="2" ItemsSource="{Binding Model.PieChartnode}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<lvchart:PieChart Grid.Row="0" LegendLocation="None" Style="{StaticResource PieChartStyle}" Margin="10,10"
Series="{Binding PieChartSeries}"/>
<TextBlock Grid.Row="1" Text="{Binding PieChartName}" Style="{StaticResource TextBlockAccentContent}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and code
public class PieChartNode
{
public SeriesCollection? PieChartSeries { get; set; }
public string? PieChartName { get; set; }
public PieChartNode(SeriesCollection? pieChartSeries, string? pieChartName)
{
PieChartSeries = pieChartSeries;
PieChartName = pieChartName;
}
}
public class PieChartDisplayModel : ViewModelBase
{
private SeriesCollection? pieChartSeriesCollection;
public SeriesCollection? PieChartSeriesCollection
{ get => pieChartSeriesCollection; set => pieChartSeriesCollection = value; }
private ObservableCollection<PieChartNode>? pieChartNode;
public ObservableCollection<PieChartNode>? PieChartnode
{ get => pieChartNode; set => pieChartNode = value; }
public PieChartDisplayModel()
{
PieChartSeriesCollection = new SeriesCollection
{
new PieSeries
{
Title = "Chrome",
Values = new ChartValues<ObservableValue> { new ObservableValue(8) },
DataLabels = true
},
new PieSeries
{
Title = "Mozilla",
Values = new ChartValues<ObservableValue> { new ObservableValue(6) },
DataLabels = true
},
new PieSeries
{
Title = "Opera",
Values = new ChartValues<ObservableValue> { new ObservableValue(10) },
DataLabels = true
},
new PieSeries
{
Title = "Explorer",
Values = new ChartValues<ObservableValue> { new ObservableValue(4) },
DataLabels = true
}
};
PieChartnode = new ObservableCollection<PieChartNode>();
for (int i = 0; i < 5; i++)
{
string nodeName = string.Format("Pie Chart {0}", i);
PieChartnode.Add(new PieChartNode(PieChartSeriesCollection, nodeName));
}
}
And Result like this Image.
Result
I am expecting those Pies display by feeded datas, but PieCharts gone...
someone has any ideas?
I am currently using Nuget packages
livecharts.wpf 0.97
materialdesign 4.6.1

you probably need one SeriesCollection for each chart, not one for all charts:
public class PieChartDisplayModel : ViewModelBase
{
private SeriesCollection GetPieChartSeriesCollection()
{
return new SeriesCollection
{
new PieSeries
{
Title = "Chrome",
Values = new ChartValues<ObservableValue> { new ObservableValue(8) },
DataLabels = true
},
new PieSeries
{
Title = "Mozilla",
Values = new ChartValues<ObservableValue> { new ObservableValue(6) },
DataLabels = true
},
new PieSeries
{
Title = "Opera",
Values = new ChartValues<ObservableValue> { new ObservableValue(10) },
DataLabels = true
},
new PieSeries
{
Title = "Explorer",
Values = new ChartValues<ObservableValue> { new ObservableValue(4) },
DataLabels = true
}
};
}
private ObservableCollection<PieChartNode>? pieChartNode;
public ObservableCollection<PieChartNode>? PieChartnode
{ get => pieChartNode; set => pieChartNode = value; }
public PieChartDisplayModel()
{
PieChartnode = new ObservableCollection<PieChartNode>();
for (int i = 0; i < 5; i++)
{
string nodeName = string.Format("Pie Chart {0}", i);
PieChartnode.Add(new PieChartNode(GetPieChartSeriesCollection(), nodeName));
}
}
}

Related

Add and Biding comboboxEdit DevExpress

Im trying to bind one combobox from my class that i linked in the context
i have this in the control
<dxe:ComboBoxEdit Width="100" Margin="5" Name="cboProduct" DisplayMember="Name"
SelectedItem="{Binding Path=DataContext.SelectedProduct, Mode=OneWay, RelativeSource={RelativeSource AncestorType=Window}}"
>
</dxe:ComboBoxEdit>
I filled the Combobox befor from code behind like this
var lsproducts = new List<Product>();
var Products =_licenseService.GetProductList();
Products.ForEach((x) => {
lsproducts.Add(new Product(x.Name, x.ProductId));
});
And im setting the SelectedProduct like this
[DataMember]
public License SelectedLicense {
get { return _SelectedLicense;}
set {
_SelectedLicense = value;
this.NotifyPropertyChanged("SelectedLicense");
}
}
public Product SelectedProduct
{
get
{
return new Product(_SelectedLicense.Product.Name,_SelectedLicense.Product.ProductId);
}
}
this.cboProduct.ItemsSource = lsproducts.ToArray();
in both cases im using the object Product
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using pd.Common.Domain;
namespace LicenceManagerWPF.Views
{
public class Product
{
public string Name { get; set; }
public ProductEnum ProductID { get; set; }
public Product(string ProductName,ProductEnum ID)
{
Name = ProductName;
ProductID = ID;
}
}
i dont know why its not selecting the product when i open the window.
i have another one
[![Shows like this][2]][2]
I dont know why its display the x mark, but when i chouse another licence it updated the combo selection
<dxe:ComboBoxEdit x:Name="cboActivationMode" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Width="100" Style="{StaticResource TabMargin}"
SelectedItem="{Binding Path=DataContext.SelectedLicense.ActivationMode, RelativeSource={RelativeSource AncestorType=Window}}"
/>
The second one its only a couple of enums values that fill like this.
cboActivationMode.Items.Add(
new DevExpress.Xpf.Editors.ComboBoxEditItem()
{ Content = Enum.GetName(typeof(ActivationMode), ActivationMode.Online), Tag = ActivationMode.Online });
How can i bind the values to a combobox?
Regards
cboActivationMode.Items.Add(
new DevExpress.Xpf.Editors.ComboBoxEditItem()
{Content = Enum.GetName(typeof(ActivationMode), ActivationMode.Offline),Tag = ActivationMode.Offline});
I tryed to do this
public partial class LicenseDetail : UserControl
{
private readonly LicenseService _licenseService;
public LicenseDetail()
{
InitializeComponent();
_licenseService = new LicenseService();
FillCombos();
}
private void FillCombos()
{
FillProducts();
FillActivationMode();
//var str = Enum.GetName(typeof(ProductEnum), ProductEnum.CDSAddIn);
//this.cboProduct.ItemsSource = new string[] { str };
}
private void FillProducts()
{
var Products = _licenseService.GetProductList();
cboProduct.ItemsSource = Products;
}
The product list is a list of Iproduct (interface), i dont get i why they made it like this but each product is diferent they implement the same baseclass and the interface
[DataContract]
public class ProductList : List<IProduct>
{
public bool Contains(ProductEnum productId)
{
return this.Any(x => x.ProductId == productId);
}
public IProduct GetProduct(ProductEnum productId)
{
return this.FirstOrDefault(x => x.ProductId == productId);
}
public void Remove(ProductEnum productId)
{
Remove(GetProduct(productId));
}
}
I changed the combo to bind like this
SelectedItem="{Binding Path=DataContext.MyProduct, RelativeSource={RelativeSource AncestorType=Window}}"
I create the property in the class like this
public IProduct MyProduct
{
get { return _MyProduct; }
set
{
_MyProduct = value;
this.NotifyPropertyChanged("MyProduct");
}
}
And assaing like this
_CustomerLicense.MyProduct = SelectedLicense.Product;
this is how the list of products is filled
public IProduct GetProduct(ProductEnum productId)
{
IProduct product = null;
var connection = GetConnection();
try
{
var sql = string.Format(Resources.GetProduct, (int)productId);
var cmd = new SqlCommand(sql, connection) { CommandType = CommandType.Text, Transaction = _transaction };
using (var rdr = new NullableDataReader(cmd.ExecuteReader()))
while (rdr.Read())
{
var productName = rdr.GetString(0);
var featureId = rdr.GetInt32(1);
var featureDesc = rdr.GetString(2);
if (product == null)
{
switch (productId)
{
case ProductEnum.PDCalc:
product = new PDCalcProduct(productId, productName);
break;
case ProductEnum.PDMaint:
product = new PDMaintProduct(productId, productName);
break;
case ProductEnum.PBDynamics:
product = new PBDynamicsProduct(productId, productName);
break;
case ProductEnum.CDSAddIn:
product = new CDSAddInProduct(productId, productName);
break;
}
}
if (product != null)
product.Features.Add(new Feature((FeatureEnum)featureId, featureDesc));
}
}
finally
{
CloseConnection(connection);
}
return product;
}
without any luck.
Regards
The SelectedProduct property should have a public setter for you to be able to set it to the currently selected value in the ComboBox:
private Product _selectedProduct;
public Product SelectedProduct
{
get { return _selectedProduct; }
set
{
_selectedProduct = value;
this.NotifyPropertyChanged("SelectedProduct");
}
}
And for the intial value to be selected, you either need to set it to a Product object that is actually in the ItemsSource (lsproducts):
viewModel.SelectedProduct = lsproducts.FirstOrDefault(x => x.Name == _SelectedLicense.Product.Name && x.ProductID == _SelectedLicense.Product.ProductId);
Or you will have to override the Equals method of your Product class:
public class Product
{
public string Name { get; set; }
public ProductEnum ProductID { get; set; }
public Product(string ProductName, ProductEnum ID)
{
Name = ProductName;
ProductID = ID;
}
public override bool Equals(object obj)
{
Product other = obj as Product;
return other != null && Name == other.Name && ProductID == other.ProductID;
}
}
I fixed like this:
I created the method :
private void GetProducts()
{
var Products = new LicenseService().GetProductList();
Products.ForEach((x) =>
{
lsproducts.Add(new Product(x.Name, x.ProductId));
});
//this.cboProduct.ItemsSource = lsproducts.ToArray();
}
Then i attached to the load of the main windows, where all the controls are
public frmCustomerLicense(CustomerLicenses cl)
{
InitializeComponent();
GetProducts();
_CustomerLicense = cl;
grdLicenses.grdLicences.SelectedItemChanged += GridRowSelected;
}
Then when one of the licenses is selected i set all the bindings
var Record = (DataRowView)grdLicenses.grdLicences.SelectedItem;
var SelectedLicense = (License)Record["License"];
var list = new LicenseService().GetActivityLog(SelectedLicense.SerialNumber)
.OrderByDescending(x => x.ActivityDate)
.ToList();
_CustomerLicense.ActivityLog = list;
_CustomerLicense.Features = new LicenseService().GetFeatures(SelectedLicense.Product.ProductId);
_CustomerLicense.Products = lsproducts;
_CustomerLicense.HasExpDate = SelectedLicense.HasExpirationDate;
//_CustomerLicense.SetLog(list);
_CustomerLicense.SelectedLicense = SelectedLicense;
//_CustomerLicense.SelectedMaintenance = SelectedLicense.Product.ProductId == ProductEnum.PDMaint ? true : false;
_CustomerLicense.SelectedProduct = lsproducts.FirstOrDefault((x) => x.ProductID == SelectedLicense.Product.ProductId);
And in my ViewClass i added this
[DataMember]
public Product SelectedProduct
{
get { return _SelectedProduct; }
set
{
_SelectedProduct = value;
this.NotifyPropertyChanged("SelectedProduct");
}
}
[DataMember]
public List<Product> Products
{
get { return _Products; }
set { _Products = value;
this.NotifyPropertyChanged("Products");
}
}
So, i set the combobox
<dxe:ComboBoxEdit Width="180" Margin="5" Name="cboProduct" DisplayMember="Name"
ItemsSource="{Binding Path=DataContext.Products, RelativeSource={RelativeSource AncestorType=Window}}"
SelectedItem="{Binding Path=DataContext.SelectedProduct, RelativeSource={RelativeSource AncestorType=Window}}"
>
</dxe:ComboBoxEdit>
Doing this works, thanks for your help mm8

Wpf listview combobox binding DisplayMemberPath not working

I have the following code in Wpf form:
public class Product
{
public string Name { get; set; }
public string Type { get; set; }
}
public class ProductWithValue
{
public Product Object_Product { get; set; }
public string Value { get; set; }
}
public class Data
{
public ObservableCollection<Product> ListProduct { get; set; }
public ObservableCollection<ProductWithValue> ListProdValue { get; set; }
}
Data data = LoadData();
lstProducts.DataContext = data;
The XAML:
<ListView Name="lstProducts" ItemsSource="{Binding Path=ListProdValue}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="23">
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.ListProduct}"
SelectedItem="{Binding Path=Object_Product, Mode=TwoWay}"
DisplayMemberPath="Name"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
LoadData example:
private Data LoadData()
{
Data data = new Data();
Product prod1 = new Product(){Name="Name1", Type = "Type1"};
Product prod2 = new Product(){Name="Name2", Type = "Type2"};
data.ListProduct = new ObservableCollection<Product>()
{
prod1,
prod2
};
data.ListProdValue = new ObservableCollection<ProductWithValue>()
{
new ProductWithValue(){ Object_Product = prod1, Value="Value" }
};
return data;
}
Evrything is fine, except the DisplayMemberPath.
The combobox itemssource is correct, the selected item is correct, but does not show the Name of the Product.
Any idea whats going wrong?
The wrong LoadData function in my code:
private Data LoadData()
{
Data data = new Data();
Product prod1 = new Product() { Name = "Name1", Type = "Type1" };
Product prod2 = new Product() { Name = "Name2", Type = "Type2" };
Product prod3 = new Product() { Name = "Name3", Type = "Type3" };
data.ListProduct = new ObservableCollection<Product>()
{
prod1,
prod2,
prod3
};
data.ListProdValue = new ObservableCollection<ProductWithValue>()
{
new ProductWithValue(){ Object_Product = new Product() { Name = "Name1", Type = "Type1" }, Value="Value1" },
new ProductWithValue(){ Object_Product = new Product() { Name = "Name2", Type = "Type2" }, Value="Value2" }
};
return data;
}

filter wpf datagrid values from a textbox

I have a textbox and a Datagrid. The datagrid has two columns name and Email address. I want to Filter the datagrid values with the value in the textbox.
You can use a ICollectionView for the DataGrid ItemSource then you can apply a Filter predicate and refesh the list when needed.
Here is a very quick example.
Xaml:
<Window x:Class="WpfApplication10.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="188" Width="288" Name="UI" >
<StackPanel DataContext="{Binding ElementName=UI}">
<TextBox Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid ItemsSource="{Binding DataGridCollection}" />
</StackPanel>
</Window>
Code:
namespace WpfApplication10
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ICollectionView _dataGridCollection;
private string _filterString;
public MainWindow()
{
InitializeComponent();
DataGridCollection = CollectionViewSource.GetDefaultView(TestData);
DataGridCollection.Filter = new Predicate<object>(Filter);
}
public ICollectionView DataGridCollection
{
get { return _dataGridCollection; }
set { _dataGridCollection = value; NotifyPropertyChanged("DataGridCollection"); }
}
public string FilterString
{
get { return _filterString; }
set
{
_filterString = value;
NotifyPropertyChanged("FilterString");
FilterCollection();
}
}
private void FilterCollection()
{
if (_dataGridCollection != null)
{
_dataGridCollection.Refresh();
}
}
public bool Filter(object obj)
{
var data = obj as TestClass;
if (data != null)
{
if (!string.IsNullOrEmpty(_filterString))
{
return data.Name.Contains(_filterString) || data.Email.Contains(_filterString);
}
return true;
}
return false;
}
public IEnumerable<TestClass> TestData
{
get
{
yield return new TestClass { Name = "1", Email = "1#test.com" };
yield return new TestClass { Name = "2", Email = "2#test.com" };
yield return new TestClass { Name = "3", Email = "3#test.com" };
yield return new TestClass { Name = "4", Email = "4#test.com" };
yield return new TestClass { Name = "5", Email = "5#test.com" };
yield return new TestClass { Name = "6", Email = "6#test.com" };
yield return new TestClass { Name = "7", Email = "7#test.com" };
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
public class TestClass
{
public string Name { get; set; }
public string Email { get; set; }
}
}
Result:

Problem with binding Stacked colums series chart to Series

i have big problem with binding Stacked Column Series to my chart.
I have
public ObservableCollection Series property in my ViewModel and try by many ways but it still not working.
This is code from ViewModel to prepare Series:
private void drawChart()
{
this.Series.Clear();
var dataValues = new List<List<SimpleDataValue>>();
int wartoscNiezalezna = 1;
for (int i = 0; i < 2; i++)
{
dataValues.Add(new List<SimpleDataValue>());
}
foreach (var item in myCollection)
{
var param = someparam;
dataValues[0].Add(new SimpleDataValue { IndependentValue = "Czujnik " + wartoscNiezalezna, DependentValue = 100 });
//czerwone
dataValues[1].Add(new SimpleDataValue { IndependentValue = "" + wartoscNiezalezna, DependentValue = 200 });
wartoscNiezalezna++;
}
var stackedSeries = Activator.CreateInstance(typeof(StackedColumnSeries)) as DefinitionSeries;
int itemnr=0;
foreach (var item in dataValues)
{
var definicja = new SeriesDefinition();
if(itemnr==0)
definicja.Title = "Stan 1";
else
definicja.Title = "Stan 2";
definicja.DependentValuePath = "DependentValue";
definicja.IndependentValuePath = "IndependentValue";
definicja.ToolTip = "asdas";
definicja.ItemsSource = item;
stackedSeries.SeriesDefinitions.Add(definicja);
itemnr++;
}
Series.Add(stackedSeries);
}
I cant bind it to:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition ItemsSource="{Binding Series}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue">
</charting:SeriesDefinition>
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
I was trying with SeriesDefinitions Collection and others.
I will be very grateful to some help.
I hope I've answered your question there
Anyway I post the second part of my answer here:
MainWindow.xaml:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition Title="Stan 1" ItemsSource="{Binding FirstCollection}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue" />
<charting:SeriesDefinition Title="Stan 2" ItemsSource="{Binding SecondCollection}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue" />
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
MainWindow.xaml.cs
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.MyChart.DataContext = new ChartModel
{
FirstCollection = Enumerable.Range(1, 10).Select(i => new SimpleDataValue { IndependentValue = "Czujnik " + i, DependentValue = 100 }).ToList(),
SecondCollection = Enumerable.Range(1, 10).Select(i => new SimpleDataValue { IndependentValue = "" + i, DependentValue = 200 }).ToList()
};
}
}
public class SimpleDataValue
{
public string IndependentValue { get; set; }
public int DependentValue { get; set; }
}
public class ChartModel
{
public List<SimpleDataValue> FirstCollection { get; set; }
public List<SimpleDataValue> SecondCollection { get; set; }
}
I am not sure with the syntax but the logic should be like below:
ViewModel
public class GraphItem {
public string IndependentValue { get; set; }
public int DependentValue1 { get; set; }
public int DependentValue2 { get; set; }
}
public class ChartViewModel
{
private List<GraphItem> itemCollection;
public List<GraphItem> ItemCollection
{
get { return itemCollection;}
set {
itemCollection=value;
OnPropertyChanged("ItemCollection");
}
}
public ChartViewModel()
{
//Bind ItemCollection
}
}
Xaml:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10" DataContext={Binding ItemCollection}">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition Title="Stan 1" ItemsSource="{Binding}" DependentValuePath="DependentValue1" IndependentValuePath="IndependentValue" />
<charting:SeriesDefinition Title="Stan 2" ItemsSource="{Binding}" DependentValuePath="DependentValue2" IndependentValuePath="IndependentValue" />
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
May this help.

ListView Binding with "IsSelected" Property of ListViewItem

I have following class
public abstract class AbsTrinityEvent
{
public event IsSelected OnSelectedEvent;
bool _IsSelected;
ITrinityEvent _objTrinityEvent;
public AbsTrinityEvent(ITrinityEvent objTrinityEvent)
{
_objTrinityEvent = objTrinityEvent;
}
public ITrinityEvent TrinityEventObj
{
set
{
_objTrinityEvent = value;
}
get
{
return _objTrinityEvent;
}
}
public int EventRefID
{
get
{
return _objTrinityEvent.EventRefID;
}
}
public string EventDescription
{
get
{
return _objTrinityEvent.EventDescription;
}
}
public string EventDateTime
{
get
{
return _objTrinityEvent.EventDateTime;
}
}
public string Site
{
get
{
return _objTrinityEvent.Site;
}
}
public int Priority
{
get
{
return _objTrinityEvent.Priority;
}
}
public string DeviceName
{
get
{
return _objTrinityEvent.DeviceName;
}
}
public bool IsAlarm
{
get
{
return _objTrinityEvent.IsAlarm;
}
}
public string OperatorName
{
get
{
return _objTrinityEvent.OperatorName;
}
}
public int SiteID
{
get
{
return _objTrinityEvent.SiteID;
}
}
public int EventSrcInstanceID
{
get
{
return _objTrinityEvent.EventSrcInstanceID;
}
}
public int EventSrcInstanceMasterDeviceID
{
get
{
return _objTrinityEvent.EventSrcInstanceMasterDeviceID;
}
}
public bool IsSelected
{
set
{
_IsSelected = value;
ItemSelectedEventArgs obj = new ItemSelectedEventArgs(_objTrinityEvent);
OnSelectedEvent(this, obj);
}
get
{
return _IsSelected;
}
}
}
public class ItemSelectedEventArgs : EventArgs
{
private ITrinityEvent _objItem;
public ItemSelectedEventArgs(ITrinityEvent objItem)
{
_objItem = objItem;
}
public ITrinityEvent SlectedNode
{
get
{
return _objItem;
}
}
}
public sealed class TrinityEventData : AbsTrinityEvent
{
public TrinityEventData(ITrinityEvent objEvent)
: base(objEvent)
{
}
}
I am binding this to my listview in code behind ( Not in XAML ) using following function
public void SetupColumnsForUnAcklist()
{
//Create Columns for listview
GridView grdView = new GridView();
grdView.Columns.Add(new GridViewColumn() { DisplayMemberBinding = new Binding() { Path = new PropertyPath("EventDescription") }, Header = "Description" });
grdView.Columns.Add(new GridViewColumn() { DisplayMemberBinding = new Binding() { Path = new PropertyPath("EventDateTime") }, Header = "Date:Time" });
grdView.Columns.Add(new GridViewColumn() { DisplayMemberBinding = new Binding() { Path = new PropertyPath("Site") }, Header = "Site" });
grdView.Columns.Add(new GridViewColumn() { DisplayMemberBinding = new Binding() { Path = new PropertyPath("DeviceName") }, Header = "Device" });
grdView.Columns.Add(new GridViewColumn() { DisplayMemberBinding = new Binding() { Path = new PropertyPath("Priority") }, Header = "Priority" });
lstview_Unack.View = grdView;
//Do Binding
if (_alarmUnAckList != null)
{
lstview_Unack.SetBinding(ListView.ItemsSourceProperty, new Binding() { Source = _alarmUnAckList });
lstview_Unack.SetBinding(ListView.IsSelectedProperty, new Binding() { Path = new PropertyPath("IsSelected") });
}
lstview_Unack.ContextMenu = contextMenu;
foreach (GridViewColumn col in grdView.Columns)
{
comboColumnList.Items.Add(col.Header as string);
}
}
My problem is, I want bind ListViewItem "IsSelected" Property to the TrinityEventData's "IsSelected" Property. How I should I do it in code behind?
First off, you're much better off doing this in XAML. It makes things much clearer and shorter. I'm going to answer in both XAML and code-behind to demonstrate this.
The easiest way is to make a Style applied to ListViewItem and using a Setter to apply the binding. On a ListViewItem, the DataContext is going to be your bound item (TrinityEventData in this case).
Assuming you had your ListView in XAML:
<ListView x:Name="lstview_Unack">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.Resources>
</ListView>
In code, you have to construct the Style, Setter, and Binding by hand:
Style listViewItemStyle = new Style { TargetType = typeof(ListViewItem) };
listViewItemStyle.Setters.Add(new Setter
{
Property = ListViewItem.IsSelectedProperty,
Value = new Binding { Path = new PropertyPath("IsSelected") }
});
lstview_Unack.Resources.Add(typeof(ListViewItem), listViewItemStyle);
There are issues with this and virtualization, however. If your ListViewItems get virtualized, you might be unselecting items in the ListView but the binding won't be firing because your ListViewItem won't exist.
What worked for me is:
<ListView x:Name="lstview_Unack">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>

Resources