0

I have a development environment with the 4.8 .net framework. I am trying to display a dictionary of this RemoteUnit class in a ListView, but the list view is remaining unpopulated even when I've confirmed the dictionary has items.

Here is my code

RemoteUnit.cs

public class RemoteUnit : INotifyPropertyChanged
{
    public string Id { get { return _uid; } set { _uid = value; NotifyPropertyChanged(); } }
    public string Name { get { return _name; } set { _name = value; NotifyPropertyChanged(); } }
    public bool Alive { get { return _alive; } set { _alive = value; NotifyPropertyChanged(); } }
    public bool Subscribed { get { return _subscribed; } set { _subscribed = value; NotifyPropertyChanged(); } }
}

RemoteUnitTab.xaml

<ListView Grid.Row="0" Name="LstRemoteUnits" Height="Auto" Margin="5,5,5,5" Background="White" ItemsSource="{Binding Path=RemoteUnits.UnitDict}">
    <ListView.View>
        <GridView AllowsColumnReorder="true" ColumnHeaderToolTip="Remote Units On Network">
            <GridView.ColumnHeaderContainerStyle>
                <Style TargetType="{x:Type GridViewColumnHeader}">
                    <Setter Property="Foreground" Value="Black" />
                </Style>
            </GridView.ColumnHeaderContainerStyle>
            <GridViewColumn DisplayMemberBinding="{Binding Path=Value.Name}" Header="Name" Width="Auto"/>
            <GridViewColumn DisplayMemberBinding="{Binding Path=Value.Alive}" Header="Alive" Width="Auto"/>
            <GridViewColumn DisplayMemberBinding="{Binding Path=Value.Subscribed}" Header="Subscribed" Width="Auto"/>
            <GridViewColumn DisplayMemberBinding="{Binding Path=Value.Id}" Header="Uid" Width="Auto"/>
        </GridView>
    </ListView.View>
</ListView>

RemoteUnitTab.xaml.cs

public partial class UnitsOnNetworkControl : UserControl
    {
        private UnitsData RemoteUnits;

        public UnitsOnNetworkControl()
        {
            InitializeComponent();

            RemoteUnits = GlobalUnitReference.GetReference();

            // .. other initialization stuff

            LstRemoteUnits.ItemsSource = RemoteUnits.UnitDict;
            LstRemoteUnits.DisplayMemberPath = "Value";
            LstRemoteUnits.SelectedValuePath = "Key";
        }
}

Like I said, the listview is remaining empty.

I found some stackoverflow answers which suggested setting the view to details, which I did like this:

LstRemoteUnits.View = System.Windows.Forms.View.Details;

but I got this error

Cannot implicitly convert type 'System.Windows.Forms.View' to 'System.Windows.Controls.ViewBase'

I am on a tight schedule and need this to work (project demonstration is due next week and I need to be working on more important things), so I am considering scrapping the dictionary binding for a temporary solution such as inserting RemoteUnit items in manually. Problem is, when I directly add the RemoteUnit class (after disabling ItemsSource) in with this:

LstRemoteUnits.Items.Add(remote_unit);

I get empty rows with no text. I tried manually setting sub items, but apparently "subitems" don't exist with my current environment because this code:

ListViewItem item = new ListViewItem();
item.SubItems.Add("foo");

returns the error

'ListViewItem' does not contain a definition for 'SubItems' and no accessible extension method 'SubItems' accepting a first argument of type 'ListViewItem' could be found (are you missing a using directive or an assembly reference?)

Like I said, I am on a tight schedule and need this field to work because its part of the primary interface. Can anyone help me with this?

Thanks.

[Edit - replaced reference to the project's name]

[Edit 2] Figured out the ListViewItem was coming from System.Windows.Controls and not System.Windows.Forms. Using the item from System.Windows.Forms fixes that part of the question.

1
  • If you use System.Collections.Generic.Dictionary for your UnitDict, as it does not implement INotifyCollectionChanged, it will not be able to notify the addition of elements to a view after it is bound to the view. For this reason, System.Collections.ObjectModel.ObservableCollection is usually used. Commented Apr 2, 2022 at 1:00

2 Answers 2

0

I think the reason that you don't see anything in your view is because the UI isn't getting notified properly.

Try changing

public partial class UnitsOnNetworkControl : UserControl
{
    private UnitsData RemoteUnits;

    public UnitsOnNetworkControl()
    {
        InitializeComponent();
        
        RemoteUnits = GlobalUnitReference.GetReference();

        // .. other initialization stuff

        LstRemoteUnits.ItemsSource = RemoteUnits.UnitDict;
        LstRemoteUnits.DisplayMemberPath = "Value";
        LstRemoteUnits.SelectedValuePath = "Key";
    }
  }

to

public partial class UnitsOnNetworkControl : UserControl, INotifyPropertyChanged
{
    private Dictionary<int, RemoteUnit> _remoteUnits = new();
    public Dictionary<int, RemoteUnit> RemoteUnits
    {
        get { return _remoteUnits; }
        set
        {
            _remoteUnits = value;
            NotifyPropertyChanged(nameof(RemoteUnits));
        }
    }

    public UnitsOnNetworkControl()
    {
        InitializeComponent();
        DatContext = this;
        RemoteUnits = GlobalUnitReference.GetReference();

        // .. other initialization stuff
    } 
    public event PropertyChangedEventHandler? PropertyChanged;

    private void NotifyPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new 
        PropertyChangedEventArgs(propertyName));
    }
 }

And then in your xaml Changed your Itemssource Property on your ListView to

ItemsSource="{Binding RemoteUnits}"

You can remove the Path in these cases or keep them. Shouldn't make a difference either way.

So what I did is I implemented the INotifyPropertyChanged Interface in the Code Behind, set Code Behind as the DataContext and made that little change in the xaml Code. With this I managed to get it to work with the code you have provived.

I have also changed the type of your RemoteUnits property from UnitsData to RemoteUnit because I don't see UnitsData anywhere else in your code so I assumed this to be a copy paste error or something.

Sign up to request clarification or add additional context in comments.

Comments

0

You have defined the ItemsSource="{Binding Path=RemoteUnits.UnitDict}" in your RemoteUnitTab.xaml.cs

To display binding source you have to define the DataContext of your control. the DataContext must contain a public property RemoteUnits or add the remote units as DataContext and change ItemsSource.

Try to add LstRemoteUnits.DataContext = RemoteUnits and ItemsSource="{Binding Path=UnitDict}"

1 Comment

I tried doing that but the list view isn't showing the items. I am concerned that listview isn't set up to display the RemoteUnit items correctly because it isn't showing them even when I directly insert them with "ListRemoteUnits.Items.Add" Also, I edited your post to replace a few references to the project's name which I missed removing when pasting my code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.