Привязать к количеству элементов в DataContext
Я хочу привязать счет/количество элементов в моем DataContext.
У меня есть объект, скажем, человек, который имеет свойство List<address>
как свойство. Я хотел бы отобразить количество адресов для этого человека, то есть: 5 или 6 или что бы это ни было.
Я пробовал {Binding Path=address#.Count}
и несколько других, но, похоже, не работает.
Любая помощь будет оценена, спасибо.
Ответы
Ответ 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();