简体   繁体   English

当引用不在ItemsSource中时,WPF绑定到ComboBox SelectedItem

[英]WPF binding to ComboBox SelectedItem when reference not in ItemsSource

I'm binding the PageMediaSize collection of a PrintQueue to the ItemSource of a ComboBox (This works fine). 我将PrintQueuePageMediaSize集合绑定到ComboBoxItemSource (这很好)。 Then I'm binding the SelectedItem of the ComboBox to the DefaultPrintTicket.PageMediaSize of the PrintQueue . 然后我将ComboBoxSelectedItem绑定到PrintQueueDefaultPrintTicket.PageMediaSize While this will set the selected value to the DefaultPrintTicket.PageMediaSize just fine it does not set the initially selected value of the ComboBox to the initial value of DefaultPrintTicket.PageMediaSize This is because the DefaultPrintTicket.PageMediaSize reference does not match any of the references in the collection. 虽然这会将选定的值设置为DefaultPrintTicket.PageMediaSize就好了,它没有将ComboBox的初始选择值设置为DefaultPrintTicket.PageMediaSize的初始值这是因为DefaultPrintTicket.PageMediaSize引用与之中的任何引用都不匹配采集。 However I don't want it to compare the objects by reference, but instead by value, but PageMediaSize does not override Equals (and I have no control over it). 但是我不希望它通过引用来比较对象,而是通过值来比较,但是PageMediaSize不会覆盖Equals(我无法控制它)。 What I'd really like to do is setup a IComparable for the ComboBox to use, but I don't see any way to do that. 我真正想做的是设置一个IComparableComboBox使用,但我没有看到任何方法。 I've tried to use a Converter , but I would need more than the value and I couldn't figured out how to pass the collection to the ConverterProperty . 我曾尝试使用Converter ,但我需要的不仅仅是值,我无法弄清楚如何将集合传递给ConverterProperty Any ideas on how to handle this problem. 关于如何处理这个问题的任何想法。

Here's my xaml 这是我的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"/>

And the code for the converter that gets the PageMediaSize collection 以及获取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();
    }
}

Edit 编辑

I tried setting the DefaultPrintTicket.PageMediaSize to the corresponding reference in the collection before InitializeComponent , but that did not work. 我尝试将DefaultPrintTicket.PageMediaSize设置为InitializeComponent之前的集合中的相应引用,但这不起作用。 It's definately setting the value when I select something from the ComboBox , but it doesn't seem to go the other way. 当我从ComboBox选择某些内容时,它肯定会设置该值,但它似乎没有其他方式。

Would it be possible to create a wrapper class for PageMediaSize and override the Equals(object) method in this wrapper class? 是否可以为PageMediaSize创建一个包装类并覆盖此包装类中的Equals(object)方法? You could then add instance of this wrapper class to your collection, so that they are no longer compared by reference. 然后,您可以将此包装类的实例添加到集合中,以便不再通过引用对它们进行比较。 Of course, you will need some code for wrapping and unwrapping your PageMediaSize instances, but that's the best way I can imagine. 当然,您需要一些代码来包装PageMediaSize包您的PageMediaSize实例,但这是我能想象到的最佳方式。

Further to juharr's answer, you could use a converter to wrap and unwrap the object. 根据juharr的回答,您可以使用转换器来包装和展开对象。

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;
        }
    }
}

Then declare your converter 然后声明你的转换器

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

In the xaml, use the converter on both ItemSource and Selected Item. 在xaml中,在ItemSource和Selected Item上使用转换器。

<ComboBox                                                               
    ItemsSource="{Binding MySource, Converter={StaticResource toTypeEqualityWrapper}}" 
    SelectedItem="{Binding MySelectedItem, Converter={StaticResource toTypeEqualityWrapper}}"                                                             
    DisplayMemberPath="Value.DisplayName" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM