Привязать к количеству элементов в DataContext - PullRequest
24 голосов
/ 27 мая 2010

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

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

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

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

Ответы [ 5 ]

28 голосов
/ 27 мая 2010

Вам необходимо связать имя свойства, а не его тип.

C #:

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

XAML:

{Binding Addresses.Count}

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

18 голосов
/ 27 мая 2010

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

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

Редактировать

Мне нравится читать ответ, думать: "Эй, это не правильно", а потом осознавать, что я его написал.

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

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

3 голосов
/ 27 мая 2010

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
    {
    }
}
1 голос
/ 27 мая 2010

Чтобы развернуть ответ 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;
        }
    }

}
0 голосов
/ 03 октября 2017

В моем случае ответ Роберта очень приблизил меня к тому, к чему я стремился. Тем не менее, я добавляю много элементов в список из сервисного вызова и не хочу, чтобы событие запускалось для каждого элемента. Для этого я воспользовался функциональностью, уже встроенной в 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...