How to use MultiBinding in a WPF ComboBox
Asked Answered
S

3

7

This is driving me NUTS!!!

I have a ComboBox used to filter a query by employee which works fine but only displays the employees first name. I want to use a MultiValueConverter to display the employees full name (This would be less urgent if we did not have 2 Mikes and 2 Daves)

Below is my working code and the IMultiValueConverter Class (With unnecessary formatting trimmed out for brevity). I have tried everything I can think of to get the MultiConverter to work but I have had no luck.

<ComboBox ItemsSource="{Binding Path=EmployeesFilter}" 
                       DisplayMemberPath="EmpFirstName"
                       SelectedValue="{Binding Path=EmployeeToShow, Mode=TwoWay}"/>

The ViewModel Properties it is bound to:

// This collection is used to populate the Employee Filter ComboBox
private ObservableCollection<Employee> employeesFilter;
public ObservableCollection<Employee> EmployeesFilter
{
    get {
            return employeesFilter;
        }
    set {
        if (employeesFilter != value)
        {
            employeesFilter = value;
            OnPropertyChanged("EmployeesFilter");
        }
    }
}

// This property is TwoWay bound to the EmployeeFilters SelectedValue
private Employee employeeToShow;
public Employee EmployeeToShow
{
    get {
            return employeeToShow;
        }
    set {
        if (employeeToShow != value)
        {
            employeeToShow = value;
            OnPropertyChanged("EmployeeToShow");
            QueryIssues(); // Requery with new employee filter
        }
    }
}

The IMultiValueConverter:

class StringsToFullNameMultiConverter : IMultiValueConverter
{
    public object Convert(object[] values, 
                          Type targetType, 
                          object parameter, 
                          System.Globalization.CultureInfo culture)
    {
        // I added this because I kept getting DependecyProperty.UnsetValue 
        // Passed in as the program initializes
        if (values[0] as string != null)
        {
            string firstName = (string)values[0];
            string lastName = (string)values[1];
            string fullName = firstName + " " + lastName;
            return fullName;
        }
        return null;
    }

    public object[] ConvertBack(object value, 
                                Type[] targetTypes, 
                                object parameter, 
                                System.Globalization.CultureInfo culture)
    {
        return null; 
    }
}

I tried a lot of different things but basically am using the following in the ComboBox

<ComboBox.SelectedValue>
     <MultiBinding Converter="{StaticResource StringsToFullNameMultiConverter}" 
                   Mode="OneWay" > 
           <Binding Path="EmpFirstName" />
           <Binding Path="EmpLastName"/>
     </MultiBinding>
</ComboBox.SelectedValue>

As it stands now the converter is called when the program initializes with the values set to DependencyProperty.UnsetValue. after that it is never called again, even when you select a name from the box. The names are still displayed as a first name.

Thanks for any help or pointers to good tutorials/samples you can provide. All the ones I keep finding on the web are for textboxes and I can use them just fine all day.

Serotine answered 4/2, 2010 at 6:27 Comment(0)
I
25

You're close! What you want to do though is ComboBox.ItemTemplate, not SelectedValue. Prepare for some XAML hell.

<ComboBox.ItemTemplate>
    <DataTemplate>
        <TextBlock>
            <TextBlock.Text>
                <MultiBinding Converter="{StaticResource StringsToFillNameMultiConverter}">
                    <Binding Path="EmpFirstName" />
                    <Binding Path="EmpLastName" />
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </DataTemplate>
</ComboBox.ItemTemplate>

Also, if I recall correctly, you don't need to create your own converter if you're just formatting strings. I think you can do the following (someone please correct me if I'm wrong.)

<!-- "Last, First" -->
<MultiBinding StringFormat="{}{1}, {0}">
    <Binding Path="EmpFirstName" />
    <Binding Path="EmpLastName" />
</MultiBinding>
Incomprehensible answered 4/2, 2010 at 6:39 Comment(4)
Oddly this works but the xaml is highlited with an error, the error reads "Property 'Text' does not support values of type 'MultiBinding'." I am sure it will be an easy fix but I am leaving it until the morning since my real issue is solved! Thanks so much for the help, I HATE going to bed with an unsolved mystery to keep me awakeSerotine
By the way, the Code you have for formatting without a converter works perfectly as it is!Serotine
That's a weird error. Sounds like it might just be a harmless Cider bug though.Incomprehensible
Found a reference to it from Microsoft on another report of this --- "Thanks for your feedback. We were able to reproduce the issue you are seeing. We are routing this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue."Serotine
N
0

You may be better of using a data template for the items, so you have complete control over how each person is displayed in the dropdown list.

The type convert is OK provided you don’t have a need to control the formatting of the different fields.

Numerology answered 4/2, 2010 at 9:1 Comment(0)
S
0

I ended up by addig a Readonly Property to my Class and use Displaymemberpath in the Combobox

public class MyEmployee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string DisplayName {
    get { return FirstName + " " + LastName; }
        }
}

Could something like this work for your situation...? BR, Daniel

Spinney answered 10/2, 2016 at 16:42 Comment(2)
Honestly I have no idea, the original question is from 2010 and is long off my radar :)Serotine
I saw it... Just meant to post my 2Cent in case someone could use it :)Spinney

© 2022 - 2024 — McMap. All rights reserved.