Подтвердить что ты не робот

Привязать к количеству элементов в DataContext

Я хочу привязать счет/количество элементов в моем DataContext.

У меня есть объект, скажем, человек, который имеет свойство List<address> как свойство. Я хотел бы отобразить количество адресов для этого человека, то есть: 5 или 6 или что бы это ни было.

Я пробовал {Binding Path=address#.Count} и несколько других, но, похоже, не работает.

Любая помощь будет оценена, спасибо.

4b9b3361

Ответ 1

Вам нужно связать имя свойства, а не его тип.

С#:

public class Person
{
    ...
    public List<address> Addresses { get; set; }
    ...
}

XAML:

{Binding Addresses.Count}

Предполагая, что ваш DataContext является объектом типа Person.

Ответ 2

Как говорит tehMick, вы можете связать, используя путь Addresses.Count.

Обратите внимание, что если Addresses не является ObservableCollection<address> или каким-либо другим типом, который реализует INotifyCollectionChanged, добавление и удаление адресов не повлияет на число, отображаемое в пользовательском интерфейсе после его первоначального отображения. Если вам это нужно, вам нужно либо изменить тип коллекции в своей модели просмотра (что проще всего), либо реализовать свойство в вашей модели представлений, которое предоставляет счет, и поднять событие PropertyChanged каждый раз, когда вы добавляете или удалите адрес.

Edit

Я люблю читать ответ, думая: "Эй, это не так", а потом понял, что я его написал.

Если вы привязываетесь к объекту, который просто реализует INotifyCollectionChanged, подсчет в пользовательском интерфейсе не изменится, если элементы будут добавлены или удалены из коллекции. Объект также должен реализовать INotifyPropertyChanged и поднять PropertyChanged при изменении свойства Count.

Что, к счастью, ObservableCollection<T> делает. Поэтому мой ответ не тот, что неправильно.

Ответ 3

XAML:

<Window x:Class="CountDemo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="CountDemo" Height="300" Width="300">
    <StackPanel>
        <TextBlock Text="{Binding Path=Addresses.Count}" />
    </StackPanel>
</Window>

Код позади:

using System.Collections.Generic;
using System.Windows;

namespace CountDemo
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            DataContext = new Person();
        }
    }

    public class Person
    {
        public List<Address> Addresses
        {
            get { return new List<Address>() {new Address(), new Address(), new Address()}; }
        }
    }

    public class Address
    {
    }
}

Ответ 4

Чтобы расшифровать ответ tehMick с помощью функционального кода примера:

XAML:

<Window x:Class="Sandbox.Wpf.PropertyCount.PropertyCount"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Property Count" Height="300" Width="300">
    <StackPanel>
        <ListView ItemsSource="{Binding Path=People}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="4">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Path=Name}" Margin="3" />
                        <TextBlock Grid.Column="1" Margin="3">
                            <TextBlock Text="{Binding Path=Addresses.Count}" /> <Run>addresses</Run>
                        </TextBlock>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>
</Window>

Код за:

namespace Sandbox.Wpf.PropertyCount
{
    /// <summary>
    /// Interaction logic for PropertyCount.xaml
    /// </summary>
    public partial class PropertyCount : Window
    {

        public PropertyCount()
        {
            InitializeComponent();
            this.DataContext = new Model();
        }
    }

    public class Model
    {
        public List<Person> People { get; private set; }

        public Model()
        {

            People = new List<Person>{
                new Person ("joe", new List<object> { 1, 2, 3 }),
                new Person ("bob", new List<object> { 1, 2 }),
                new Person ("kay", new List<object> { 1, 2, 3, 4, 5 }),
                new Person ("jill", new List<object> { 1, 2, 3, 4 }),
            };
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public List<object> Addresses { get; set; }

        public Person(string name, List<object> addresses)
        {
            Name = name;
            Addresses = addresses;
        }
    }

}

Ответ 5

В моем случае Роберт ответил, что я действительно близок к тому, что мне нужно. Тем не менее, я добавляю много элементов в список из вызова службы и не хочу, чтобы событие срабатывало для каждого элемента. Для этого я воспользовался функциональностью, уже встроенной в BindingList:

public class BindingListNotifyCount<T> : BindingList<T>, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected override void OnListChanged(ListChangedEventArgs e)
    {
        base.OnListChanged(e);
        RaisePropertyChanged("Count");
    }

    protected void RaisePropertyChanged([CallerMemberName]string propertyName = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Тогда я просто использую его как:

displayItems.RaiseListChangedEvents = false;
serviceItems.ForEach(item => displayItems.Add(item));
displayItems.RaiseListChangedEvents = true;
displayItems.ResetBindings();