6

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?

GEOCHET
  • 21,119
  • 15
  • 74
  • 98

2 Answers2

17

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.

Robert Macnee
  • 11,650
  • 4
  • 40
  • 35
  • 1
    Thanks for this thorough answer. I was having a lot of trouble figuring out how to do this! – sourcenouveau Sep 11 '09 at 12:36
  • I've just encountered that problem with virtualisation. Is there a good solution to it short of not virtualising the panel? – Miral Aug 04 '11 at 05:56
  • 1
    @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. – Robert Macnee Aug 09 '11 at 15:00
  • @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 Aug 05 '21 at 10:10
  • 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` – nietras Aug 05 '21 at 13:14
3

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>
teocomi
  • 874
  • 1
  • 11
  • 21