В WPF как двусторонне связать IsChecked свойства Checkbox со свойством List <>. Содержит? - PullRequest
0 голосов
/ 13 июня 2018

Извините, если формулировка моего вопроса не очень хорошая или если на него где-то был дан ответ, я искал, но я не знаю, насколько хорошо объяснить, что я пытаюсь сделать.

Вот простой тестовый стенд, который я частично настроил, чтобы помочь объяснить:

MainWindow.xaml:

<Window x:Class="wpfExample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:wpfExample"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ListView Grid.Column="0" ItemsSource="{Binding People}" DisplayMemberPath="Name"/>

    <ListBox Grid.Column="1" ItemsSource="{Binding Interests}" Margin="0,4,4,4">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox Content="{Binding Name}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>

MainWindow.xaml.cs:

using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace wpfExample
{
    public class Person
    {
        public string Name { get; set; }
        public ObservableCollection<Guid> Interests { get; set; }
    }

    public class Interest
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

    public class Data
    {
        public ObservableCollection<Person> People { get; set; }
        public ObservableCollection<Interest> Interests { get; set; }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            DataContext = new Data
            {
                People = new ObservableCollection<Person>
                {
                    new Person {Name="Fred", Interests=new ObservableCollection<Guid>() },
                    new Person {Name="Jane", Interests=new ObservableCollection<Guid>() },
                    new Person {Name="Zach", Interests=new ObservableCollection<Guid>() }
                },
                Interests = new ObservableCollection<Interest>
                {
                    new Interest {Name="Gardening", Id=Guid.NewGuid() },
                    new Interest {Name="Writing", Id=Guid.NewGuid() },
                    new Interest {Name="Avoiding Tax", Id=Guid.NewGuid() }
                }
            };

            InitializeComponent();
        }
    }
}

Итак, у меня есть DataContext, который содержит два списка.Один содержит интересы, которые имеют имя и идентификатор.Другой содержит людей, у которых есть имя и список идентификаторов интересов.

Когда человек выбран в пользовательском интерфейсе, я хочу иметь возможность добавлять и удалять идентификаторы интересов в соответствующем списке, следовательно,ListView в столбце 1 привязан к списку интересов, но как правильно связать свойство IsChecked флажков в списке?

В моем полном проекте я смог успешно прочитать свойствасписок интересов выбранного лица с использованием MultiBinding для IsChecked с MultiValueConverter для одновременной передачи идентификатора интереса и списка интересов человека (поскольку нельзя использовать привязку с параметром для «нормального» преобразователя значения).Я чувствую, что это решение немного злоупотребляет конвертером, но я рад придерживаться его в случае необходимости.

Как мне внедрить систему, которая позволит мне добавлять и удалять интересующие гидык списку интересов человека, когда флажок установлен?Есть ли более чистый способ сделать это?Я не хочу менять модель, если этого можно избежать.

1 Ответ

0 голосов
/ 13 июня 2018

Я бы не сказал, что ваше решение MultiConverter является злоупотреблением;вы делаете именно то, что должны преобразователи (взять набор данных и преобразовать его в целевой тип, а затем вернуться назад).

При этом;Конвертеры немного беспорядочные из-за их общности (использование object), а для мультиконвертеров это удваивается, поэтому, если вы хотите другое решение, я бы порекомендовал создать оболочку модели представления для Interest;скажем Selectable<T>:

public class Selectable<T>
{
     public T Data {get; set;}
     public bool Selected {get; set;}
}

Затем обновите вашу собственность

public ObservableCollection<Selectable<Interest>> Interests { get; set; }

И привяжите IsChecked непосредственно к Selected

Затем, когда выбранный Personизменено, вы можете соответствующим образом обновить свойство Selected;сохранить предыдущее значение для другого Person и т. д. Это несколько зависит от того, когда действие пользователя должно быть отражено в модели.

С учетом всего сказанного оба подхода будут совершенно правильными, это просто сводится к тому, что вам наиболее удобно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...