WPF привязка к Listbox selectedItem

EDIT: Это теперь часть MoreLINQ .

Что вам нужно, это «отличная» эффективность. Я не верю, что это часть LINQ в ее нынешнем виде, хотя ее довольно легко написать:

public static IEnumerable DistinctBy
    (this IEnumerable source, Func keySelector)
{
    HashSet seenKeys = new HashSet();
    foreach (TSource element in source)
    {
        if (seenKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

Итак, чтобы найти различные значения, используя только свойство Id, вы можете использовать:

var query = people.DistinctBy(p => p.Id);

И для использования нескольких свойств вы можете использовать анонимные типы, которые соответствующим образом реализуют равенство:

var query = people.DistinctBy(p => new { p.Id, p.Name });

Untested, но он должен работать (и теперь он, по крайней мере, компилируется).

Он предполагает сопоставление по умолчанию для ключей, хотя - если вы хотите передать в компаратор равенства, просто передайте его конструктору HashSet.

30
задан Kjartan 22 January 2018 в 09:27
поделиться

4 ответа

Прежде всего, необходимо реализовать интерфейс INotifyPropertyChanged в вашей модели представления и поднять событие PropertyChanged в настройке свойства Rule. В противном случае ни один элемент управления, связанный со свойством SelectedRule, не будет "знать" при его изменении.

Тогда ваш XAML

<TextBlock Text="{Binding Path=SelectedRule.Name}" />

будет полностью действителен, если этот TextBlock находится вне свойства ListBox ItemTemplate и имеет тот же DataContext, что и ListBox.

25
ответ дан 28 November 2019 в 00:19
поделиться
[

] Yocoder прав, [

] [

] Внутри [] DataTemplate [] ваш [] DataContext [] установлен на [] Правило [], с которым он работает в данный момент. [

] [

]Для доступа к родительскому []DataContext[], вы также можете рассмотреть возможность использования []RelativeSource[] в вашей привязке:[

] [
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ____Your Parent control here___ }}, Path=DataContext.SelectedRule.Name}" />
] [

]Больше информации о []RelativeSource[] можно найти здесь:[

] [

][]http://msdn. microsoft.com/en-us/library/system.windows.data.relativesource. aspx[][

]
3
ответ дан 28 November 2019 в 00:19
поделиться
[

]Внутри []DataTemplate[] вы работаете в контексте []Rule[], поэтому вы не можете привязать его к []SelectedRule. Имя[] -- в []Правиле[] такого свойства нет. Для привязки к исходному контексту данных (которым является ваша ViewModel) вы можете написать:[

] [
<TextBlock Text="{Binding ElementName=lbRules, Path=DataContext.SelectedRule.Name}" />
] [

][]UPDATE:[] относительно привязки свойства SelectedItem, оно выглядит вполне корректно, я попробовал то же самое на своей машине, и оно работает нормально. Вот мое полное тестовое приложение:[

] [

]XAML:[

] [
<Window x:Class="TestWpfApplication.ListBoxSelectedItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ListBoxSelectedItem" Height="300" Width="300"
    xmlns:app="clr-namespace:TestWpfApplication">
    <Window.DataContext>
        <app:ListBoxSelectedItemViewModel/>
    </Window.DataContext>
    <ListBox ItemsSource="{Binding Path=Rules}" SelectedItem="{Binding Path=SelectedRule, Mode=TwoWay}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Name:" />
                    <TextBox Text="{Binding Name}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Window>
] [

]Код за:[

] [
namespace TestWpfApplication
{
    /// <summary>
    /// Interaction logic for ListBoxSelectedItem.xaml
    /// </summary>
    public partial class ListBoxSelectedItem : Window
    {
        public ListBoxSelectedItem()
        {
            InitializeComponent();
        }
    }


    public class Rule
    {
        public string Name { get; set; }
    }

    public class ListBoxSelectedItemViewModel
    {
        public ListBoxSelectedItemViewModel()
        {
            Rules = new ObservableCollection<Rule>()
            {
                new Rule() { Name = "Rule 1"},
                new Rule() { Name = "Rule 2"},
                new Rule() { Name = "Rule 3"},
            };
        }

        public ObservableCollection<Rule> Rules { get; private set; }

        private Rule selectedRule;
        public Rule SelectedRule
        {
            get { return selectedRule; }
            set
            {
                selectedRule = value;
            }
        }
    }
}
]
11
ответ дан 28 November 2019 в 00:19
поделиться

поскольку вы устанавливаете источник элементов в свою коллекцию, ваш текстовый ящик привязан к каждому отдельному элементу в этой коллекции. свойство выбранного элемента полезно в этом сценарии, если вы пытались создать мастер-форму детализации, имея 2 ящика со списками. вы бы привязывали источник элементов второго ящика к дочерней коллекции правил. в других словах выбранный элемент предупреждает внешние элементы управления, что ваш источник изменился, внутренние элементы управления (те, кто находится внутри вашей таблицы данных, уже знают об изменении).

и для ответа на вопрос "да" в большинстве случаев настройка источника элементов аналогична настройке текста элемента управления.

-7
ответ дан 28 November 2019 в 00:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: