xaml привязать значение элемента списка к тому, является ли

Я создаю приложение WPF в VS 2012, которое использует Code First Entity Framework, репозиторий и шаблон MVVM.

У меня два класса: EntityType и LicenseType.

EntityType определяется следующим:

    private int _id;
    private string _name;
    private string _description;
    private List<LicenseType> _licenseTypes = new List<LicenseType>();

LicenseType объявляется с помощью:

    private int _id;
    private string _name;
    private string _description;

И для этих частных полей объявлены публичные свойства.

Я привязываю ObservableCollection к CheckedListBox (продукт Syncfusion).

Без проблем.

Под ним я привязываю еще один CheckedListBox к ObservableCollection.

Опять же, без проблем.

Что я не могу сделать, так это установить для свойства IsSelected элемента CheckListBoxItem в списке LicenseType значение true (тем самым «проверяя» флажок) в зависимости от того, находится ли этот конкретный LicenseType в коллекции EntityType.LicenseTypes.

Вот код моего CheckedListBox:

         <syncfusion:CheckListBox x:Name="lstAllLicenseTypes" ItemsSource="{Binding   AllLicenseTypes}" DisplayMemberPath="Name" >
           <syncfusion:CheckListBox.ItemContainerStyle>
                <Style TargetType="syncfusion:CheckListBoxItem">
                    <Setter Property="IsSelected" Value="{Binding ????}"/>
                </Style>
            </syncfusion:CheckListBox.ItemContainerStyle>
        </syncfusion:CheckListBox>

Я пробовал два подхода, первый заключался в том, чтобы перебрать каждый из элементов списка LicenseType, проверить, была ли связь с коллекцией LicenseType EntityType, и попытаться установить значение свойства, которое было привязано к XAML:

private void ListEntityTypes_OnSelectionChanged (отправитель объекта, SelectionChangedEventArgs e) {var thisEntity = (EntityType) listEntityTypes.SelectedItems [0];

        foreach (object t in lstAllLicenseTypes.Items)
        {
            bool hasAssociation = _vmEntityTypes.EntityHasAssociationWithThisLicenseType(thisEntity,(LicenseType) t);
            if (hasAssociation)
            {
                _vmEntityTypes.CurrentEntityIsAssociatedWithCurrentLicenseType = true;
            }
            else
            {
                _vmEntityTypes.CurrentEntityIsAssociatedWithCurrentLicenseType = false;
            }
        }

    }

Цель здесь - привязать к свойству CurrentEntityIsAssociatedWithCurrentLicenseType. Это не сработало. Я думаю, что это не сработало, потому что для каждого элемента в CheckedListBox значение свойства было обновлено, и поэтому в конце оно было ложным, поэтому ни один элемент не был проверен.

Другой подход был аналогичен описанному выше, но я пытался вручную «проверить» элемент списка, однако мне никогда не удавалось вернуть LicenseType в CheckListItem.

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

Любая помощь была бы замечательной,

Спасибо! Павел


person Paul Mc    schedule 14.02.2013    source источник


Ответы (1)


Используйте конвертер. Привяжите IsChecked к свойству, которое является оболочкой для списка (EntityType.LicenseTypes), а затем используйте IValueConverter, который возвращает логическое значение. Передайте LicenseType для CheckedListBoxItem как ConverterParameter.

Реализуйте IPropertyNofity в классе EntityType.

При изменении списка EntityType.LicenseTypes используйте PropertyNotify для обернутого свойства, и isChecked обновится.

Псевдокод:

public class EntityType : INotifyPropertyChanged
{
    ...
    public List<LicenseType> LicenseTypes
    { 
        get { return _licenseTypes; }
        set
        {
            _licenseTypes = value;
            OnNotifyPropertyChanged("LicenseTypes");
        }
    }

}

public class ListToCheckedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter ...
    {
        var list = (List<LicenseType>)value;
        var type = (LicenseType)parameter;
        return list.Contains(type);
    }
    ...
}

XAML:

    <syncfusion:CheckListBox x:Name="lstAllLicenseTypes" ItemsSource="{Binding   AllLicenseTypes}" DisplayMemberPath="Name" >
       <syncfusion:CheckListBox.ItemContainerStyle>
            <Style TargetType="syncfusion:CheckListBoxItem">
                <Setter Property="IsSelected" 
                    Value="{Binding Path=LicenseTypes, 
                            Converter = ListToCheckedConverter,
                            ConverterParameter = Header}"/>
            </Style>
        </syncfusion:CheckListBox.ItemContainerStyle>
    </syncfusion:CheckListBox>
person Lee Louviere    schedule 14.02.2013
comment
В качестве альтернативы вы можете привязать IsSelected к самому заголовку CheckedListBoxItem и передать EntityList, но тогда вы потеряете возможность автоматического обновления, если EntityList обновляется. - person Lee Louviere; 15.02.2013
comment
В качестве альтернативы, в качестве альтернативы вы можете использовать multibind и связывать как Header, так и EntityList, и если они обновляются. Всего несколько идей. - person Lee Louviere; 15.02.2013
comment
Я реализовал изменения, которые вы дали в первом решении, однако функция Converter НЕ работает. Вот код: - person Paul Mc; 15.02.2013
comment
открытый класс ListToCheckedConverter: IValueConverter {открытый объект Convert (значение объекта, тип targetType, параметр объекта, культура CultureInfo) {var list = (ObservableCollection ‹LicenseType›) значение; параметр var type = (LicenseType); return list.Contains (тип); } открытый объект ConvertBack (значение объекта, тип targetType, параметр объекта, культура CultureInfo) {throw new NotImplementedException (); }} - person Paul Mc; 15.02.2013
comment
Функция IValueConverter Convert НЕ запускается. - person Paul Mc; 19.02.2013
comment
Тогда, скорее всего, путь привязки не разрешен правильно. Я посмотрю на это, когда у меня будет больше времени. - person Lee Louviere; 27.02.2013