ListView Binding with "IsSelected" Property of ListViewItem

17,571

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>
Share:
17,571
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    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
    sourcenouveau over 14 years
    Thanks for this thorough answer. I was having a lot of trouble figuring out how to do this!
  • Miral
    Miral almost 13 years
    I've just encountered that problem with virtualisation. Is there a good solution to it short of not virtualising the panel?
  • Robert Macnee
    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
    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
    nietras almost 3 years
    actually 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 the SelectionChangedEventArgs