Louis S. Berman
Louis S. Berman

Reputation: 994

WPF ComboBox Display Issue

I have a ComboBox that's bound to a Collection of User objects. The combo's DisplayMemberPath is set to "Name," a property of the User object. I also have a textbox that is bound to the same object that ComboBox.SelectedItem is bound to. As such, when I change the text in the TextBox, my change gets immediately reflected in the combo. This is exactly what I want to happen as long as the Name property isn't set to blank. In such a case, I'd like to substitute a generic piece of text, such as "{Please Supply a Name}". Unfortunately, I couldn't figure out how to do so, so any help in this regard would be greatly appreciated!

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"
    Width="340"
    SizeToContent="Height"
    WindowStartupLocation="CenterScreen"
    ResizeMode="NoResize">
<StackPanel>
    <TextBlock Text="ComboBox:" />
    <ComboBox SelectedItem="{Binding SelectedUser}"
              DisplayMemberPath="Name"
              ItemsSource="{Binding Users}" />
    <TextBlock Text="TextBox:"
               Margin="0,8,0,0" />
    <TextBox Text="{Binding SelectedUser.Name, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>

public class ViewModel : INotifyPropertyChanged
{
    private List<User> users;
    private User selectedUser;

    public event PropertyChangedEventHandler PropertyChanged;

    public List<User> Users
    {
        get
        {
            return users;
        }
        set
        {
            if (users == value)
                return;

            users = value;

            RaisePropertyChanged("Users");
        }
    }

    public User SelectedUser
    {
        get
        {
            return selectedUser;
        }
        set
        {
            if (selectedUser == value)
                return;

            selectedUser = value;

            RaisePropertyChanged("SelectedUser");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class User
{
    public string Name { get; set; }
}

Upvotes: 1

Views: 1856

Answers (2)

Phil
Phil

Reputation: 43021

You can make use of TargetNullValue

<StackPanel>
    <TextBlock Text="ComboBox:" />
    <ComboBox SelectedItem="{Binding SelectedUser}" ItemsSource="{Binding Users}" >
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock 
                    Text="{Binding Name, TargetNullValue='Enter some text'}"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
    <TextBlock Text="TextBox:"
        Margin="0,8,0,0" />
    <TextBox Text=
             "{Binding SelectedUser.Name, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>

and convert an empty name to null.

public class User 
{
    private string name;

    public string Name
    {
        get
        {
            return this.name;
        }
        set
        {
            this.name = (string.IsNullOrEmpty(value)) ? null : value;

            // probably best raise property changed here
        }
    }
}

Upvotes: 0

Mash
Mash

Reputation: 1536

Take a look at this post. There are several answers that may meet your requirement.

Upvotes: 1

Related Questions