Привязка WPF к ComboBox SelectedItem, когда ссылка отсутствует в ItemsSource - PullRequest
6 голосов
/ 03 июня 2010

Я связываю PageMediaSize коллекцию PrintQueue с ItemSource из ComboBox (это прекрасно работает). Затем я связываю SelectedItem ComboBox с DefaultPrintTicket.PageMediaSize PrintQueue. Несмотря на то, что это установит выбранное значение на DefaultPrintTicket.PageMediaSize просто отлично, оно не установит первоначально выбранное значение ComboBox на начальное значение DefaultPrintTicket.PageMediaSize Это потому, что ссылка DefaultPrintTicket.PageMediaSize не соответствует ни одной из ссылок в коллекции. Однако я не хочу сравнивать объекты по ссылке, а по значению, но PageMediaSize не переопределяет Equals (и я не могу это контролировать). Что я действительно хотел бы сделать, так это настроить IComparable для использования ComboBox, но я не вижу никакого способа сделать это. Я пытался использовать Converter, но мне нужно больше, чем значение, и я не мог понять, как передать коллекцию в ConverterProperty. Любые идеи о том, как справиться с этой проблемой.

Вот мой xaml

<ComboBox x:Name="PaperSizeComboBox" 
          ItemsSource="{Binding ElementName=PrintersComboBox, Path=SelectedItem, 
                        Converter={StaticResource printQueueToPageSizesConverter}}"
          SelectedItem="{Binding ElementName=PrintersComboBox, 
                         Path=SelectedItem.DefaultPrintTicket.PageMediaSize}"
          DisplayMemberPath="PageMediaSizeName"
          Height="22"
          Margin="120,76,15,0"
          VerticalAlignment="Top"/>

И код для конвертера, который получает коллекцию PageMediaSize

public class PrintQueueToPageSizesConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                          System.Globalization.CultureInfo culture)
    {
        return value == null ? null :
            ((PrintQueue)value).GetPrintCapabilities().PageMediaSizeCapability;
    }

    public object ConvertBack(object value, Type targetType, object parameter, 
                          System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

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

Я пытался установить DefaultPrintTicket.PageMediaSize на соответствующую ссылку в коллекции до InitializeComponent, но это не сработало. Это определенно устанавливает значение, когда я выбираю что-то из ComboBox, но, похоже, оно не идет другим путем.

Ответы [ 2 ]

3 голосов
/ 04 июня 2010

Можно ли создать класс оболочки для PageMediaSize и переопределить метод Equals(object) в этом классе оболочки? Затем вы можете добавить экземпляр этого класса-оболочки в вашу коллекцию, чтобы они больше не сравнивались по ссылке. Конечно, вам понадобится код для упаковки и распаковки ваших PageMediaSize экземпляров, но это лучший способ, который я могу себе представить.

1 голос
/ 04 ноября 2015

В дополнение к ответу Джухарра, вы можете использовать конвертер, чтобы обернуть и развернуть объект.

using System;
using System.Collections;
using System.Globalization;
using System.Linq;
using System.Windows.Data;

namespace MyNameSpace
{
    public class ToTypeEqualityWrapper : IValueConverter
    {
        public class TypeEqualityWrapper
        {
            public object Value { get; set; }

            public TypeEqualityWrapper(object value)
            {
                Value = value;
            }

            public override bool Equals(object obj)
            {
                var otherWrapper = obj as TypeEqualityWrapper;
                if (otherWrapper == null)
                    return false;

                var result = Value.GetType().FullName == otherWrapper.Value.GetType().FullName;
                return result;
            }
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var list = value as IList;
            if (list != null)
            {
                return (from object item in list select new TypeEqualityWrapper(item)).Cast<object>().ToList();
            }

            return new TypeEqualityWrapper(value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var wrapper = value as TypeEqualityWrapper;
            if(wrapper != null)
                return wrapper.Value;

            return value;
        }
    }
}

Тогда объявите свой конвертер

<ns:ToTypeEqualityWrapper x:Key="toTypeEqualityWrapper" />    

В xaml используйте конвертер как для ItemSource, так и для Selected Item.

<ComboBox                                                               
    ItemsSource="{Binding MySource, Converter={StaticResource toTypeEqualityWrapper}}" 
    SelectedItem="{Binding MySelectedItem, Converter={StaticResource toTypeEqualityWrapper}}"                                                             
    DisplayMemberPath="Value.DisplayName" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...