ListView Binding with "IsSelected" Property of ListViewItem
Solution 1
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.
Solution 2
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>
Admin
Updated on June 05, 2022Comments
-
Admin almost 2 years
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?
-
sourcenouveau over 14 yearsThanks for this thorough answer. I was having a lot of trouble figuring out how to do this!
-
Miral almost 13 yearsI've just encountered that problem with virtualisation. Is there a good solution to it short of not virtualising the panel?
-
Robert Macnee almost 13 years@Miral: I wouldn't call it a "good" solution, but we handle this for our own ListView by not using a Binding at all, but instead listening for selection changes on both sides and manually syncing the ListView.SelectedItems and a similar observable collection in the bound ViewModel class. We sync the ViewModel from the ListView by overriding OnSelectionChanged, and sync the ListView from the ViewModel by listening to changes to the observable collection on the ViewModel.
-
nietras almost 3 years@RobertMacnee we are having the virtualization issue do you have some full example show casing this, perhaps we could create a question/answer here on SO for that. I'm not sure I fully understand how you do this...
-
nietras almost 3 yearsactually I think I got, it's pretty basic if you just have a
IsSelected
property on your item view models, then simply update these based on theSelectionChangedEventArgs